From cc19c968a02b18e42882a57b5db7355ecb8362e3 2011-08-19 06:11:50 From: Brian E. Granger Date: 2011-08-19 06:11:50 Subject: [PATCH] Making JSON the default .ipynb format. --- diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 7a794a9..7540e76 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -3526,7 +3526,7 @@ Defaulting color scheme to 'NoColor'""" 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 (xml/ipynb, json, py). + formats include (json/ipynb, py). """ args = magic_arguments.parse_argstring(self.magic_notebook, s) @@ -3544,17 +3544,21 @@ Defaulting color scheme to 'NoColor'""" 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' or new_format == u'ipynb': + 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'xml' + new_format = u'json' elif new_format == u'py': new_fname = old_name + u'.py' - elif new_format == u'json': - new_fname = old_name + u'.json' else: - raise ValueError('Invalid notebook format: %s' % newformat) + raise ValueError('Invalid notebook format: %s' % new_format) with open(old_fname, 'r') as f: - nb = current.read(f, old_format) + s = f.read() + try: + nb = current.reads(s, old_format) + except: + nb = current.reads(s, u'xml') with open(new_fname, 'w') as f: current.write(nb, f, new_format) diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index 93d0568..c006e46 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -282,9 +282,6 @@ class NotebookHandler(web.RequestHandler): if format == u'json': 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', 'application/xml') - self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name) elif format == u'py': self.set_header('Content-Type', 'application/x-python') self.set_header('Content-Disposition','attachment; filename="%s.py"' % name) diff --git a/IPython/frontend/html/notebook/notebookmanager.py b/IPython/frontend/html/notebook/notebookmanager.py index 74017d4..a02dbc8 100644 --- a/IPython/frontend/html/notebook/notebookmanager.py +++ b/IPython/frontend/html/notebook/notebookmanager.py @@ -39,7 +39,7 @@ class NotebookManager(LoggingConfigurable): The directory to use for notebooks. """) filename_ext = Unicode(u'.ipynb') - allowed_formats = List([u'json',u'xml',u'py']) + allowed_formats = List([u'json',u'py']) # Map notebook_ids to notebook names mapping = Dict() @@ -120,19 +120,15 @@ class NotebookManager(LoggingConfigurable): raise web.HTTPError(404) info = os.stat(path) last_modified = datetime.datetime.utcfromtimestamp(info.st_mtime) - try: - with open(path,'r') as f: - s = f.read() - try: - # v2 and later have xml in the .ipynb files. - nb = current.reads(s, 'xml') - except: - # v1 had json in the .ipynb files. - nb = current.reads(s, 'json') - # v1 notebooks don't have a name field, so use the filename. - nb.name = os.path.split(path)[-1].split(u'.')[0] - except: - raise web.HTTPError(404) + with open(path,'r') as f: + s = f.read() + try: + # v1 and v2 and json in the .ipynb files. + nb = current.reads(s, u'json') + except: + raise web.HTTPError(404) + if 'name' not in nb: + nb.name = os.path.split(path)[-1].split(u'.')[0] return last_modified, nb def save_new_notebook(self, data, name=None, format=u'json'): @@ -147,14 +143,7 @@ class NotebookManager(LoggingConfigurable): try: nb = current.reads(data, format) except: - if format == u'xml': - # v1 notebooks might come in with a format='xml' but be json. - try: - nb = current.reads(data, u'json') - except: - raise web.HTTPError(400) - else: - raise web.HTTPError(400) + raise web.HTTPError(400) if name is None: try: @@ -175,14 +164,7 @@ class NotebookManager(LoggingConfigurable): try: nb = current.reads(data, format) except: - if format == u'xml': - # v1 notebooks might come in with a format='xml' but be json. - try: - nb = current.reads(data, u'json') - except: - raise web.HTTPError(400) - else: - raise web.HTTPError(400) + raise web.HTTPError(400) if name is not None: nb.name = name @@ -200,7 +182,7 @@ class NotebookManager(LoggingConfigurable): path = self.get_path_by_name(new_name) try: with open(path,'w') as f: - current.write(nb, f, u'xml') + current.write(nb, f, u'json') except: raise web.HTTPError(400) if old_name != new_name: @@ -231,6 +213,6 @@ class NotebookManager(LoggingConfigurable): notebook_id = self.new_notebook_id(name) nb = current.new_notebook(name=name) with open(path,'w') as f: - current.write(nb, f, u'xml') + current.write(nb, f, u'json') return notebook_id diff --git a/IPython/frontend/html/notebook/static/js/notebooklist.js b/IPython/frontend/html/notebook/static/js/notebooklist.js index 5aa380a..2a0c6d9 100644 --- a/IPython/frontend/html/notebook/static/js/notebooklist.js +++ b/IPython/frontend/html/notebook/static/js/notebooklist.js @@ -39,8 +39,8 @@ var IPython = (function (IPython) { var fname = f.name.split('.'); var nbname = fname[0]; var nbformat = fname[1]; - if (nbformat === 'ipynb') {nbformat = 'xml';}; - if (nbformat === 'xml' || nbformat === 'py' || nbformat === 'json') { + if (nbformat === 'ipynb') {nbformat = 'json';}; + if (nbformat === 'py' || nbformat === 'json') { var item = that.new_notebook_item(0); that.add_name_input(nbname, item); item.data('nbformat', nbformat); @@ -198,9 +198,7 @@ var IPython = (function (IPython) { 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') { + if (nbformat === 'json') { content_type = 'application/json'; } else if (nbformat === 'py') { content_type = 'application/x-python'; diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html index 7e52294..f0afcc9 100644 --- a/IPython/frontend/html/notebook/templates/notebook.html +++ b/IPython/frontend/html/notebook/templates/notebook.html @@ -62,7 +62,6 @@
@@ -72,7 +71,7 @@ - +
diff --git a/IPython/nbformat/current.py b/IPython/nbformat/current.py index 316dfe3..39bb833 100644 --- a/IPython/nbformat/current.py +++ b/IPython/nbformat/current.py @@ -127,7 +127,7 @@ def reads(s, format, **kwargs): ---------- s : str The raw string to read the notebook from. - format : ('xml','json','py') + format : ('json','py') The format that the string is in. Returns @@ -154,7 +154,7 @@ def writes(nb, format, **kwargs): ---------- nb : NotebookNode The notebook to write. - format : ('xml','json','py') + format : ('json','py') The format to write the notebook in. Returns @@ -182,7 +182,7 @@ def read(fp, format, **kwargs): ---------- fp : file Any file-like object with a read method. - format : ('xml','json','py') + format : ('json','py') The format that the string is in. Returns @@ -204,7 +204,7 @@ def write(nb, fp, format, **kwargs): The notebook to write. fp : file Any file-like object with a write method. - format : ('xml','json','py') + format : ('json','py') The format to write the notebook in. Returns diff --git a/IPython/nbformat/v2/__init__.py b/IPython/nbformat/v2/__init__.py index 64de9a0..5919a71 100644 --- a/IPython/nbformat/v2/__init__.py +++ b/IPython/nbformat/v2/__init__.py @@ -43,13 +43,13 @@ def parse_filename(fname): """Parse a notebook filename. This function takes a notebook filename and returns the notebook - format (xml/json/py) and the notebook name. This logic can be + format (json/py) and the notebook name. This logic can be summarized as follows: - * notebook.ipynb -> (notebook.ipynb, notebook, xml) + * notebook.ipynb -> (notebook.ipynb, notebook, json) * notebook.json -> (notebook.json, notebook, json) * notebook.py -> (notebook.py, notebook, py) - * notebook -> (notebook.ipynb, notebook, xml) + * notebook -> (notebook.ipynb, notebook, json) Parameters ---------- @@ -64,14 +64,14 @@ def parse_filename(fname): The filename, notebook name and format. """ if fname.endswith(u'.ipynb'): - format = u'xml' + format = u'json' elif fname.endswith(u'.json'): format = u'json' elif fname.endswith(u'.py'): format = u'py' else: fname = fname + u'.ipynb' - format = u'xml' + format = u'json' name = fname.split('.')[0] return fname, name, format diff --git a/IPython/nbformat/v2/nbxml.py b/IPython/nbformat/v2/nbxml.py index 7419e50..4bd55e4 100644 --- a/IPython/nbformat/v2/nbxml.py +++ b/IPython/nbformat/v2/nbxml.py @@ -17,6 +17,7 @@ Authors: #----------------------------------------------------------------------------- from base64 import encodestring, decodestring +import warnings from xml.etree import ElementTree as ET from .rwbase import NotebookReader, NotebookWriter @@ -110,6 +111,8 @@ class XMLReader(NotebookReader): return self.to_notebook(root, **kwargs) def to_notebook(self, root, **kwargs): + warnings.warn('The XML notebook format is no longer supported, ' + 'please convert your notebooks to JSON.', DeprecationWarning) nbname = _get_text(root,u'name') nbauthor = _get_text(root,u'author') nbemail = _get_text(root,u'email') @@ -179,6 +182,8 @@ class XMLReader(NotebookReader): class XMLWriter(NotebookWriter): def writes(self, nb, **kwargs): + warnings.warn('The XML notebook format is no longer supported, ' + 'please convert your notebooks to JSON.', DeprecationWarning) nb_e = ET.Element(u'notebook') _set_text(nb,u'name',nb_e,u'name') _set_text(nb,u'author',nb_e,u'author') diff --git a/IPython/nbformat/v2/tests/test_xml.py b/IPython/nbformat/v2/tests/test_xml.py deleted file mode 100644 index 45cc2e1..0000000 --- a/IPython/nbformat/v2/tests/test_xml.py +++ /dev/null @@ -1,18 +0,0 @@ -from unittest import TestCase - -from ..nbxml import reads, writes -from .nbexamples import nb0 -import pprint - -class TestXML(TestCase): - - def test_roundtrip(self): - s = writes(nb0) -# print -# print pprint.pformat(nb0,indent=2) -# print -# print pprint.pformat(reads(s),indent=2) -# print -# print s - self.assertEquals(reads(s),nb0) -