diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index 7b618fbde09..b6cb9f7649a 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -41,12 +41,12 @@ def get(self, notebook_id): class KernelHandler(web.RequestHandler): def get(self): - self.write(json.dumps(self.application.kernel_ids)) + self.finish(json.dumps(self.application.kernel_ids)) def post(self): kernel_id = self.application.start_kernel() self.set_header('Location', '/'+kernel_id) - self.write(json.dumps(kernel_id)) + self.finish(json.dumps(kernel_id)) class KernelActionHandler(web.RequestHandler): @@ -58,6 +58,7 @@ def post(self, kernel_id, action): if action == 'restart': new_kernel_id = self.application.restart_kernel(kernel_id) self.write(json.dumps(new_kernel_id)) + self.finish() class ZMQStreamHandler(websocket.WebSocketHandler): @@ -83,7 +84,7 @@ class NotebookRootHandler(web.RequestHandler): def get(self): nbm = self.application.notebook_manager files = nbm.list_notebooks() - self.write(json.dumps(files)) + self.finish(json.dumps(files)) def post(self): nbm = self.application.notebook_manager @@ -95,7 +96,7 @@ def post(self): else: notebook_id = nbm.new_notebook() self.set_header('Location', '/'+notebook_id) - self.write(json.dumps(notebook_id)) + self.finish(json.dumps(notebook_id)) class NotebookHandler(web.RequestHandler): @@ -110,10 +111,10 @@ def get(self, notebook_id): self.set_header('Content-Type', 'application/json') self.set_header('Content-Disposition','attachment; filename=%s.json' % name) elif format == u'xml': - self.set_header('Content-Type', 'text/xml') + self.set_header('Content-Type', 'application/xml') self.set_header('Content-Disposition','attachment; filename=%s.ipynb' % name) elif format == u'py': - self.set_header('Content-Type', 'text/plain') + self.set_header('Content-Type', 'application/x-python') self.set_header('Content-Disposition','attachment; filename=%s.py' % name) self.set_header('Last-Modified', last_mod) self.finish(data) diff --git a/IPython/frontend/html/notebook/static/js/notebook.js b/IPython/frontend/html/notebook/static/js/notebook.js index 792e51b574b..2db0cecd6e7 100644 --- a/IPython/frontend/html/notebook/static/js/notebook.js +++ b/IPython/frontend/html/notebook/static/js/notebook.js @@ -559,11 +559,12 @@ var IPython = (function (IPython) { data.id = notebook_id // We do the call with settings so we can set cache to false. var settings = { - processData : false, - cache : false, - type : "PUT", - data : JSON.stringify(data), - success : $.proxy(this.notebook_saved,this) + processData : false, + cache : false, + type : "PUT", + data : JSON.stringify(data), + headers : {'Content-Type': 'application/json'}, + success : $.proxy(this.notebook_saved,this) }; IPython.save_widget.status_saving(); $.ajax("/notebooks/" + notebook_id, settings); diff --git a/IPython/frontend/html/notebook/static/js/notebooklist.js b/IPython/frontend/html/notebook/static/js/notebooklist.js index 76dfdfa5107..531cce43a2e 100644 --- a/IPython/frontend/html/notebook/static/js/notebooklist.js +++ b/IPython/frontend/html/notebook/static/js/notebooklist.js @@ -191,12 +191,21 @@ var IPython = (function (IPython) { var nbname = item.find('.item_name > input').attr('value'); var nbformat = item.data('nbformat'); var nbdata = item.data('nbdata'); + var content_type = 'text/plain'; + if (nbformat === 'xml') { + content_type = 'application/xml'; + } else if (nbformat === 'json') { + content_type = 'application/json'; + } else if (nbformat === 'py') { + content_type = 'application/x-python'; + }; var settings = { processData : false, cache : false, - type : "POST", - dataType : "json", + type : 'POST', + dataType : 'json', data : nbdata, + headers : {'Content-Type': content_type}, success : function (data, status, xhr) { that.add_link(data, nbname, item); that.add_delete_button(item); @@ -204,7 +213,7 @@ var IPython = (function (IPython) { }; var qs = $.param({name:nbname, format:nbformat}); - $.ajax("/notebooks?" + qs, settings); + $.ajax('/notebooks?' + qs, settings); }); var cancel_button = $('').button(). click(function (e) { diff --git a/IPython/nbformat/current.py b/IPython/nbformat/current.py index c587bacd72d..757c20e0689 100644 --- a/IPython/nbformat/current.py +++ b/IPython/nbformat/current.py @@ -43,7 +43,7 @@ def parse_py(s, **kwargs): if m is not None: nbformat = int(m.group('nbformat')) else: - raise NBFormatError('No nbformat version found') + nbformat = 2 return nbformat, s diff --git a/IPython/nbformat/v2/nbpy.py b/IPython/nbformat/v2/nbpy.py index aa775ff0771..8bbbc0dad11 100644 --- a/IPython/nbformat/v2/nbpy.py +++ b/IPython/nbformat/v2/nbpy.py @@ -4,6 +4,10 @@ from .nbbase import new_code_cell, new_worksheet, new_notebook +class PyReaderError(Exception): + pass + + class PyReader(NotebookReader): def reads(self, s, **kwargs): @@ -13,20 +17,42 @@ def to_notebook(self, s, **kwargs): lines = s.splitlines() cells = [] cell_lines = [] + code_cell = False for line in lines: if line.startswith(u'# '): + if code_cell: + raise PyReaderError('Unexpected ') + if cell_lines: + for block in self.split_lines_into_blocks(cell_lines): + cells.append(new_code_cell(input=block)) cell_lines = [] + code_cell = True if line.startswith(u'# '): + if not code_cell: + raise PyReaderError('Unexpected ') code = u'\n'.join(cell_lines) code = code.strip(u'\n') if code: cells.append(new_code_cell(input=code)) + code_cell = False else: cell_lines.append(line) + # For lines we were not able to process, + for block in self.split_lines_into_blocks(cell_lines): + cells.append(new_code_cell(input=block)) ws = new_worksheet(cells=cells) nb = new_notebook(worksheets=[ws]) return nb + def split_lines_into_blocks(self, lines): + import ast + source = '\n'.join(lines) + code = ast.parse(source) + starts = [x.lineno-1 for x in code.body] + for i in range(len(starts)-1): + yield '\n'.join(lines[starts[i]:starts[i+1]]).strip('\n') + yield '\n'.join(lines[starts[-1]:]).strip('\n') + class PyWriter(NotebookWriter): diff --git a/IPython/nbformat/v2/tests/test_nbpy.py b/IPython/nbformat/v2/tests/test_nbpy.py index a51ac426138..4c12c4e4b4e 100644 --- a/IPython/nbformat/v2/tests/test_nbpy.py +++ b/IPython/nbformat/v2/tests/test_nbpy.py @@ -15,4 +15,3 @@ def test_write(self): s = writes(nb0) self.assertEquals(s,nb0_py) -