From 482c7bd67eb06652b9a89b4bf4e034a40cf0b61c 2014-11-03 17:58:33 From: Thomas Kluyver Date: 2014-11-03 17:58:33 Subject: [PATCH] Merge pull request #6045 from minrk/nbformat4 nbformat v4 --- diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 31fa45e..a6b395e 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2649,14 +2649,14 @@ class InteractiveShell(SingletonConfigurable): def get_cells(): """generator for sequence of code blocks to run""" if fname.endswith('.ipynb'): - from IPython.nbformat import current - with open(fname) as f: - nb = current.read(f, 'json') - if not nb.worksheets: + from IPython.nbformat import read + with io_open(fname) as f: + nb = read(f, as_version=4) + if not nb.cells: return - for cell in nb.worksheets[0].cells: + for cell in nb.cells: if cell.cell_type == 'code': - yield cell.input + yield cell.source else: with open(fname) as f: yield f.read() diff --git a/IPython/core/magics/basic.py b/IPython/core/magics/basic.py index 827f72c..c4c48cb 100644 --- a/IPython/core/magics/basic.py +++ b/IPython/core/magics/basic.py @@ -1,25 +1,12 @@ -"""Implementation of basic magic functions. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- +"""Implementation of basic magic functions.""" + from __future__ import print_function -# Stdlib import io import json import sys from pprint import pformat -# Our own packages from IPython.core import magic_arguments, page from IPython.core.error import UsageError from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes @@ -30,9 +17,6 @@ from IPython.utils.path import unquote_filename from IPython.utils.py3compat import unicode_type from IPython.utils.warn import warn, error -#----------------------------------------------------------------------------- -# Magics class implementation -#----------------------------------------------------------------------------- class MagicsDisplay(object): def __init__(self, magics_manager): @@ -599,13 +583,6 @@ Defaulting color scheme to 'NoColor'""" 'file extension will write the notebook as a Python script' ) @magic_arguments.argument( - '-f', '--format', - help='Convert an existing IPython notebook to a new format. This option ' - 'specifies the new format and can have the values: json, py. ' - 'The target filename is chosen automatically based on the new ' - 'format. The filename argument gives the name of the source file.' - ) - @magic_arguments.argument( 'filename', type=unicode_type, help='Notebook name or filename' ) @@ -613,41 +590,22 @@ Defaulting color scheme to 'NoColor'""" def notebook(self, s): """Export and convert IPython notebooks. - This function can export the current IPython history to a notebook file - or can convert an existing notebook file into a different format. For - example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb". - To export the history to "foo.py" do "%notebook -e foo.py". To convert - "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible - formats include (json/ipynb, py). + This function can export the current IPython history to a notebook file. + For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb". + To export the history to "foo.py" do "%notebook -e foo.py". """ args = magic_arguments.parse_argstring(self.notebook, s) - from IPython.nbformat import current + from IPython.nbformat import write, v4 args.filename = unquote_filename(args.filename) if args.export: - fname, name, format = current.parse_filename(args.filename) cells = [] hist = list(self.shell.history_manager.get_range()) - for session, prompt_number, input in hist[:-1]: - cells.append(current.new_code_cell(prompt_number=prompt_number, - input=input)) - worksheet = current.new_worksheet(cells=cells) - nb = current.new_notebook(name=name,worksheets=[worksheet]) - with io.open(fname, 'w', encoding='utf-8') as f: - current.write(nb, f, format); - elif args.format is not None: - old_fname, old_name, old_format = current.parse_filename(args.filename) - new_format = args.format - if new_format == u'xml': - raise ValueError('Notebooks cannot be written as xml.') - elif new_format == u'ipynb' or new_format == u'json': - new_fname = old_name + u'.ipynb' - new_format = u'json' - elif new_format == u'py': - new_fname = old_name + u'.py' - else: - raise ValueError('Invalid notebook format: %s' % new_format) - with io.open(old_fname, 'r', encoding='utf-8') as f: - nb = current.read(f, old_format) - with io.open(new_fname, 'w', encoding='utf-8') as f: - current.write(nb, f, new_format) + for session, execution_count, input in hist[:-1]: + cells.append(v4.new_code_cell( + execution_count=execution_count, + source=source + )) + nb = v4.new_notebook(cells=cells) + with io.open(args.filename, 'w', encoding='utf-8') as f: + write(nb, f, version=4) diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index ea617bc..acd0d3d 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -5,10 +5,6 @@ Needs to be run by nose (to make ipython session available). """ from __future__ import absolute_import -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - import io import os import sys @@ -40,9 +36,6 @@ if py3compat.PY3: else: from StringIO import StringIO -#----------------------------------------------------------------------------- -# Test functions begin -#----------------------------------------------------------------------------- @magic.magics_class class DummyMagics(magic.Magics): pass @@ -624,7 +617,7 @@ def test_extension(): # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf -@skipIf(dec.module_not_available('IPython.nbformat.current'), 'nbformat not importable') +@skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable') class NotebookExportMagicTests(TestCase): def test_notebook_export_json(self): with TemporaryDirectory() as td: @@ -632,35 +625,6 @@ class NotebookExportMagicTests(TestCase): _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) _ip.magic("notebook -e %s" % outfile) - def test_notebook_export_py(self): - with TemporaryDirectory() as td: - outfile = os.path.join(td, "nb.py") - _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) - _ip.magic("notebook -e %s" % outfile) - - def test_notebook_reformat_py(self): - from IPython.nbformat.v3.tests.nbexamples import nb0 - from IPython.nbformat import current - with TemporaryDirectory() as td: - infile = os.path.join(td, "nb.ipynb") - with io.open(infile, 'w', encoding='utf-8') as f: - current.write(nb0, f, 'json') - - _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) - _ip.magic("notebook -f py %s" % infile) - - def test_notebook_reformat_json(self): - from IPython.nbformat.v3.tests.nbexamples import nb0 - from IPython.nbformat import current - with TemporaryDirectory() as td: - infile = os.path.join(td, "nb.py") - with io.open(infile, 'w', encoding='utf-8') as f: - current.write(nb0, f, 'py') - - _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) - _ip.magic("notebook -f ipynb %s" % infile) - _ip.magic("notebook -f json %s" % infile) - def test_env(): env = _ip.magic("env") diff --git a/IPython/core/tests/test_run.py b/IPython/core/tests/test_run.py index 2816e36..2316a3d 100644 --- a/IPython/core/tests/test_run.py +++ b/IPython/core/tests/test_run.py @@ -7,11 +7,12 @@ will be kept in this separate file. This makes it easier to aggregate in one place the tricks needed to handle it; most other magics are much easier to test and we do so in a common test_magic file. """ + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + from __future__ import absolute_import -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- import functools import os @@ -32,9 +33,6 @@ from IPython.utils.io import capture_output from IPython.utils.tempdir import TemporaryDirectory from IPython.core import debugger -#----------------------------------------------------------------------------- -# Test functions begin -#----------------------------------------------------------------------------- def doctest_refbug(): """Very nasty problem with references held by multiple runs of a script. @@ -372,19 +370,17 @@ tclass.py: deleting object: C-third with tt.AssertNotPrints('SystemExit'): _ip.magic('run -e %s' % self.fname) - @dec.skip_without('IPython.nbformat.current') # Requires jsonschema + @dec.skip_without('IPython.nbformat') # Requires jsonschema def test_run_nb(self): """Test %run notebook.ipynb""" - from IPython.nbformat import current - nb = current.new_notebook( - worksheets=[ - current.new_worksheet(cells=[ - current.new_text_cell("The Ultimate Question of Everything"), - current.new_code_cell("answer=42") - ]) + from IPython.nbformat import v4, writes + nb = v4.new_notebook( + cells=[ + v4.new_markdown_cell("The Ultimate Question of Everything"), + v4.new_code_cell("answer=42") ] ) - src = current.writes(nb, 'json') + src = writes(nb, version=4) self.mktmp(src, ext='.ipynb') _ip.magic("run %s" % self.fname) diff --git a/IPython/html/nbconvert/handlers.py b/IPython/html/nbconvert/handlers.py index f6e1094..9fa4482 100644 --- a/IPython/html/nbconvert/handlers.py +++ b/IPython/html/nbconvert/handlers.py @@ -13,7 +13,7 @@ from ..base.handlers import ( IPythonHandler, FilesRedirectHandler, notebook_path_regex, path_regex, ) -from IPython.nbformat.current import to_notebook_json +from IPython.nbformat import from_dict from IPython.utils.py3compat import cast_bytes @@ -114,14 +114,15 @@ class NbconvertPostHandler(IPythonHandler): exporter = get_exporter(format, config=self.config) model = self.get_json_body() - nbnode = to_notebook_json(model['content']) + name = model.get('name', 'notebook.ipynb') + nbnode = from_dict(model['content']) try: output, resources = exporter.from_notebook_node(nbnode) except Exception as e: raise web.HTTPError(500, "nbconvert failed: %s" % e) - if respond_zip(self, nbnode.metadata.name, output, resources): + if respond_zip(self, name, output, resources): return # MIME type diff --git a/IPython/html/nbconvert/tests/test_nbconvert_handlers.py b/IPython/html/nbconvert/tests/test_nbconvert_handlers.py index ea44217..88ff3a7 100644 --- a/IPython/html/nbconvert/tests/test_nbconvert_handlers.py +++ b/IPython/html/nbconvert/tests/test_nbconvert_handlers.py @@ -10,9 +10,10 @@ import requests from IPython.html.utils import url_path_join from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error -from IPython.nbformat.current import (new_notebook, write, new_worksheet, - new_heading_cell, new_code_cell, - new_output) +from IPython.nbformat import write +from IPython.nbformat.v4 import ( + new_notebook, new_markdown_cell, new_code_cell, new_output, +) from IPython.testing.decorators import onlyif_cmds_exist @@ -43,7 +44,8 @@ class NbconvertAPI(object): png_green_pixel = base64.encodestring(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00' b'\x00\x00\x01\x00\x00x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDAT' -b'\x08\xd7c\x90\xfb\xcf\x00\x00\x02\\\x01\x1e.~d\x87\x00\x00\x00\x00IEND\xaeB`\x82') +b'\x08\xd7c\x90\xfb\xcf\x00\x00\x02\\\x01\x1e.~d\x87\x00\x00\x00\x00IEND\xaeB`\x82' +).decode('ascii') class APITest(NotebookTestBase): def setUp(self): @@ -52,19 +54,20 @@ class APITest(NotebookTestBase): if not os.path.isdir(pjoin(nbdir, 'foo')): os.mkdir(pjoin(nbdir, 'foo')) - nb = new_notebook(name='testnb') + nb = new_notebook() - ws = new_worksheet() - nb.worksheets = [ws] - ws.cells.append(new_heading_cell(u'Created by test ³')) - cc1 = new_code_cell(input=u'print(2*6)') - cc1.outputs.append(new_output(output_text=u'12', output_type='stream')) - cc1.outputs.append(new_output(output_png=png_green_pixel, output_type='pyout')) - ws.cells.append(cc1) + nb.cells.append(new_markdown_cell(u'Created by test ³')) + cc1 = new_code_cell(source=u'print(2*6)') + cc1.outputs.append(new_output(output_type="stream", text=u'12')) + cc1.outputs.append(new_output(output_type="execute_result", + data={'image/png' : png_green_pixel}, + execution_count=1, + )) + nb.cells.append(cc1) with io.open(pjoin(nbdir, 'foo', 'testnb.ipynb'), 'w', encoding='utf-8') as f: - write(nb, f, format='ipynb') + write(nb, f, version=4) self.nbconvert_api = NbconvertAPI(self.base_url()) diff --git a/IPython/html/services/contents/filemanager.py b/IPython/html/services/contents/filemanager.py index 8077de1..81e36c6 100644 --- a/IPython/html/services/contents/filemanager.py +++ b/IPython/html/services/contents/filemanager.py @@ -12,7 +12,7 @@ import shutil from tornado import web from .manager import ContentsManager -from IPython.nbformat import current +from IPython import nbformat from IPython.utils.io import atomic_writing from IPython.utils.path import ensure_dir_exists from IPython.utils.traitlets import Unicode, Bool, TraitError @@ -253,9 +253,9 @@ class FileContentsManager(ContentsManager): os_path = self._get_os_path(name, path) with io.open(os_path, 'r', encoding='utf-8') as f: try: - nb = current.read(f, u'json') + nb = nbformat.read(f, as_version=4) except Exception as e: - raise web.HTTPError(400, u"Unreadable Notebook: %s %s" % (os_path, e)) + raise web.HTTPError(400, u"Unreadable Notebook: %s %r" % (os_path, e)) self.mark_trusted_cells(nb, name, path) model['content'] = nb model['format'] = 'json' @@ -295,7 +295,7 @@ class FileContentsManager(ContentsManager): def _save_notebook(self, os_path, model, name='', path=''): """save a notebook file""" # Save the notebook file - nb = current.to_notebook_json(model['content']) + nb = nbformat.from_dict(model['content']) self.check_and_sign(nb, name, path) @@ -303,7 +303,7 @@ class FileContentsManager(ContentsManager): nb['metadata']['name'] = u'' with atomic_writing(os_path, encoding='utf-8') as f: - current.write(nb, f, version=nb.nbformat) + nbformat.write(nb, f, version=nbformat.NO_CONVERT) def _save_file(self, os_path, model, name='', path=''): """save a non-notebook file""" @@ -522,7 +522,7 @@ class FileContentsManager(ContentsManager): # ensure notebook is readable (never restore from an unreadable notebook) if cp_path.endswith('.ipynb'): with io.open(cp_path, 'r', encoding='utf-8') as f: - current.read(f, u'json') + nbformat.read(f, as_version=4) self._copy(cp_path, nb_path) self.log.debug("copying %s -> %s", cp_path, nb_path) diff --git a/IPython/html/services/contents/manager.py b/IPython/html/services/contents/manager.py index bdff6e8..6058160 100644 --- a/IPython/html/services/contents/manager.py +++ b/IPython/html/services/contents/manager.py @@ -11,7 +11,8 @@ import os from tornado.web import HTTPError from IPython.config.configurable import LoggingConfigurable -from IPython.nbformat import current, sign +from IPython.nbformat import sign, validate, ValidationError +from IPython.nbformat.v4 import new_notebook from IPython.utils.traitlets import Instance, Unicode, List @@ -220,8 +221,8 @@ class ContentsManager(LoggingConfigurable): def validate_notebook_model(self, model): """Add failed-validation message to model""" try: - current.validate(model['content']) - except current.ValidationError as e: + validate(model['content']) + except ValidationError as e: model['message'] = 'Notebook Validation failed: {}:\n{}'.format( e.message, json.dumps(e.instance, indent=1, default=lambda obj: ''), ) @@ -234,8 +235,7 @@ class ContentsManager(LoggingConfigurable): model = {} if 'content' not in model and model.get('type', None) != 'directory': if ext == '.ipynb': - metadata = current.new_metadata(name=u'') - model['content'] = current.new_notebook(metadata=metadata) + model['content'] = new_notebook() model['type'] = 'notebook' model['format'] = 'json' else: @@ -309,14 +309,12 @@ class ContentsManager(LoggingConfigurable): Parameters ---------- nb : dict - The notebook object (in nbformat.current format) + The notebook dict name : string The filename of the notebook (for logging) path : string The notebook's directory (for logging) """ - if nb['nbformat'] != current.nbformat: - return if self.notary.check_cells(nb): self.notary.sign(nb) else: @@ -330,7 +328,7 @@ class ContentsManager(LoggingConfigurable): Parameters ---------- nb : dict - The notebook object (in nbformat.current format) + The notebook object (in current nbformat) name : string The filename of the notebook (for logging) path : string diff --git a/IPython/html/services/contents/tests/test_contents_api.py b/IPython/html/services/contents/tests/test_contents_api.py index bac91de..b62dbb3 100644 --- a/IPython/html/services/contents/tests/test_contents_api.py +++ b/IPython/html/services/contents/tests/test_contents_api.py @@ -14,9 +14,10 @@ import requests from IPython.html.utils import url_path_join, url_escape from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error -from IPython.nbformat import current -from IPython.nbformat.current import (new_notebook, write, read, new_worksheet, - new_heading_cell, to_notebook_json) +from IPython.nbformat import read, write, from_dict +from IPython.nbformat.v4 import ( + new_notebook, new_markdown_cell, +) from IPython.nbformat import v2 from IPython.utils import py3compat from IPython.utils.data import uniq_stable @@ -142,8 +143,8 @@ class APITest(NotebookTestBase): # create a notebook with io.open(pjoin(nbdir, d, '%s.ipynb' % name), 'w', encoding='utf-8') as f: - nb = new_notebook(name=name) - write(nb, f, format='ipynb') + nb = new_notebook() + write(nb, f, version=4) # create a text file with io.open(pjoin(nbdir, d, '%s.txt' % name), 'w', @@ -286,14 +287,14 @@ class APITest(NotebookTestBase): self.assertEqual(model['content'], '') def test_upload_untitled(self): - nb = new_notebook(name='Upload test') + nb = new_notebook() nbmodel = {'content': nb, 'type': 'notebook'} resp = self.api.upload_untitled(path=u'å b', body=json.dumps(nbmodel)) self._check_created(resp, 'Untitled0.ipynb', u'å b') def test_upload(self): - nb = new_notebook(name=u'ignored') + nb = new_notebook() nbmodel = {'content': nb, 'type': 'notebook'} resp = self.api.upload(u'Upload tést.ipynb', path=u'å b', body=json.dumps(nbmodel)) @@ -354,8 +355,7 @@ class APITest(NotebookTestBase): self._check_created(resp, u'Upload tést.ipynb', u'å b') resp = self.api.read(u'Upload tést.ipynb', u'å b') data = resp.json() - self.assertEqual(data['content']['nbformat'], current.nbformat) - self.assertEqual(data['content']['orig_nbformat'], 2) + self.assertEqual(data['content']['nbformat'], 4) def test_copy_untitled(self): resp = self.api.copy_untitled(u'ç d.ipynb', path=u'å b') @@ -415,22 +415,20 @@ class APITest(NotebookTestBase): def test_save(self): resp = self.api.read('a.ipynb', 'foo') nbcontent = json.loads(resp.text)['content'] - nb = to_notebook_json(nbcontent) - ws = new_worksheet() - nb.worksheets = [ws] - ws.cells.append(new_heading_cell(u'Created by test ³')) + nb = from_dict(nbcontent) + nb.cells.append(new_markdown_cell(u'Created by test ³')) nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb, 'type': 'notebook'} resp = self.api.save('a.ipynb', path='foo', body=json.dumps(nbmodel)) nbfile = pjoin(self.notebook_dir.name, 'foo', 'a.ipynb') with io.open(nbfile, 'r', encoding='utf-8') as f: - newnb = read(f, format='ipynb') - self.assertEqual(newnb.worksheets[0].cells[0].source, + newnb = read(f, as_version=4) + self.assertEqual(newnb.cells[0].source, u'Created by test ³') nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] - newnb = to_notebook_json(nbcontent) - self.assertEqual(newnb.worksheets[0].cells[0].source, + newnb = from_dict(nbcontent) + self.assertEqual(newnb.cells[0].source, u'Created by test ³') # Save and rename @@ -454,11 +452,9 @@ class APITest(NotebookTestBase): # Modify it nbcontent = json.loads(resp.text)['content'] - nb = to_notebook_json(nbcontent) - ws = new_worksheet() - nb.worksheets = [ws] - hcell = new_heading_cell('Created by test') - ws.cells.append(hcell) + nb = from_dict(nbcontent) + hcell = new_markdown_cell('Created by test') + nb.cells.append(hcell) # Save nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb, 'type': 'notebook'} resp = self.api.save('a.ipynb', path='foo', body=json.dumps(nbmodel)) @@ -468,15 +464,15 @@ class APITest(NotebookTestBase): self.assertEqual(cps, [cp1]) nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] - nb = to_notebook_json(nbcontent) - self.assertEqual(nb.worksheets[0].cells[0].source, 'Created by test') + nb = from_dict(nbcontent) + self.assertEqual(nb.cells[0].source, 'Created by test') # Restore cp1 r = self.api.restore_checkpoint('a.ipynb', 'foo', cp1['id']) self.assertEqual(r.status_code, 204) nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] - nb = to_notebook_json(nbcontent) - self.assertEqual(nb.worksheets, []) + nb = from_dict(nbcontent) + self.assertEqual(nb.cells, []) # Delete cp1 r = self.api.delete_checkpoint('a.ipynb', 'foo', cp1['id']) diff --git a/IPython/html/services/contents/tests/test_manager.py b/IPython/html/services/contents/tests/test_manager.py index d5dfff4..1d419bf 100644 --- a/IPython/html/services/contents/tests/test_manager.py +++ b/IPython/html/services/contents/tests/test_manager.py @@ -9,7 +9,7 @@ from tornado.web import HTTPError from unittest import TestCase from tempfile import NamedTemporaryFile -from IPython.nbformat import current +from IPython.nbformat import v4 as nbformat from IPython.utils.tempdir import TemporaryDirectory from IPython.utils.traitlets import TraitError @@ -95,11 +95,9 @@ class TestContentsManager(TestCase): return os_path def add_code_cell(self, nb): - output = current.new_output("display_data", output_javascript="alert('hi');") - cell = current.new_code_cell("print('hi')", outputs=[output]) - if not nb.worksheets: - nb.worksheets.append(current.new_worksheet()) - nb.worksheets[0].cells.append(cell) + output = nbformat.new_output("display_data", {'application/javascript': "alert('hi');"}) + cell = nbformat.new_code_cell("print('hi')", outputs=[output]) + nb.cells.append(cell) def new_notebook(self): cm = self.contents_manager @@ -309,13 +307,13 @@ class TestContentsManager(TestCase): nb, name, path = self.new_notebook() cm.mark_trusted_cells(nb, name, path) - for cell in nb.worksheets[0].cells: + for cell in nb.cells: if cell.cell_type == 'code': assert not cell.metadata.trusted cm.trust_notebook(name, path) nb = cm.get_model(name, path)['content'] - for cell in nb.worksheets[0].cells: + for cell in nb.cells: if cell.cell_type == 'code': assert cell.metadata.trusted diff --git a/IPython/html/services/sessions/tests/test_sessions_api.py b/IPython/html/services/sessions/tests/test_sessions_api.py index 9623415..4090c34 100644 --- a/IPython/html/services/sessions/tests/test_sessions_api.py +++ b/IPython/html/services/sessions/tests/test_sessions_api.py @@ -11,7 +11,8 @@ pjoin = os.path.join from IPython.html.utils import url_path_join from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error -from IPython.nbformat.current import new_notebook, write +from IPython.nbformat.v4 import new_notebook +from IPython.nbformat import write class SessionAPI(object): """Wrapper for notebook API calls.""" @@ -62,8 +63,8 @@ class SessionAPITest(NotebookTestBase): with io.open(pjoin(nbdir, 'foo', 'nb1.ipynb'), 'w', encoding='utf-8') as f: - nb = new_notebook(name='nb1') - write(nb, f, format='ipynb') + nb = new_notebook() + write(nb, f, version=4) self.sess_api = SessionAPI(self.base_url()) diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js index c6d19c8..8ae55b5 100644 --- a/IPython/html/static/notebook/js/codecell.js +++ b/IPython/html/static/notebook/js/codecell.js @@ -382,13 +382,11 @@ define([ CodeCell.prototype.collapse_output = function () { - this.collapsed = true; this.output_area.collapse(); }; CodeCell.prototype.expand_output = function () { - this.collapsed = false; this.output_area.expand(); this.output_area.unscroll_area(); }; @@ -399,7 +397,6 @@ define([ }; CodeCell.prototype.toggle_output = function () { - this.collapsed = Boolean(1 - this.collapsed); this.output_area.toggle_output(); }; @@ -467,22 +464,18 @@ define([ CodeCell.prototype.fromJSON = function (data) { Cell.prototype.fromJSON.apply(this, arguments); if (data.cell_type === 'code') { - if (data.input !== undefined) { - this.set_text(data.input); + if (data.source !== undefined) { + this.set_text(data.source); // make this value the starting point, so that we can only undo // to this state, instead of a blank cell this.code_mirror.clearHistory(); this.auto_highlight(); } - if (data.prompt_number !== undefined) { - this.set_input_prompt(data.prompt_number); - } else { - this.set_input_prompt(); - } + this.set_input_prompt(data.execution_count); this.output_area.trusted = data.metadata.trusted || false; this.output_area.fromJSON(data.outputs); - if (data.collapsed !== undefined) { - if (data.collapsed) { + if (data.metadata.collapsed !== undefined) { + if (data.metadata.collapsed) { this.collapse_output(); } else { this.expand_output(); @@ -494,16 +487,17 @@ define([ CodeCell.prototype.toJSON = function () { var data = Cell.prototype.toJSON.apply(this); - data.input = this.get_text(); + data.source = this.get_text(); // is finite protect against undefined and '*' value if (isFinite(this.input_prompt_number)) { - data.prompt_number = this.input_prompt_number; + data.execution_count = this.input_prompt_number; + } else { + data.execution_count = null; } var outputs = this.output_area.toJSON(); data.outputs = outputs; - data.language = 'python'; data.metadata.trusted = this.output_area.trusted; - data.collapsed = this.output_area.collapsed; + data.metadata.collapsed = this.output_area.collapsed; return data; }; diff --git a/IPython/html/static/notebook/js/maintoolbar.js b/IPython/html/static/notebook/js/maintoolbar.js index 6bb0f1b..becca07 100644 --- a/IPython/html/static/notebook/js/maintoolbar.js +++ b/IPython/html/static/notebook/js/maintoolbar.js @@ -139,12 +139,6 @@ define([ .append($('