##// END OF EJS Templates
add `nbformat.writes(version=X)` for downgrade...
MinRK -
Show More
@@ -1,213 +1,209 b''
1 """The official API for working with notebooks in the current format version."""
1 """The official API for working with notebooks in the current format version."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 from __future__ import print_function
6 from __future__ import print_function
7
7
8 import re
8 import re
9
9
10 from IPython.utils.py3compat import unicode_type
10 from IPython.utils.py3compat import unicode_type
11
11
12 from IPython.nbformat.v3 import (
12 from IPython.nbformat.v3 import (
13 NotebookNode,
13 NotebookNode,
14 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
14 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
15 parse_filename, new_metadata, new_author, new_heading_cell, nbformat,
15 parse_filename, new_metadata, new_author, new_heading_cell, nbformat,
16 nbformat_minor, nbformat_schema, to_notebook_json
16 nbformat_minor, nbformat_schema, to_notebook_json
17 )
17 )
18 from IPython.nbformat import v3 as _v_latest
18 from IPython.nbformat import v3 as _v_latest
19
19
20 from .reader import reads as reader_reads
20 from .reader import reads as reader_reads
21 from .reader import versions
21 from .reader import versions
22 from .convert import convert
22 from .convert import convert
23 from .validator import validate, ValidationError
23 from .validator import validate, ValidationError
24
24
25 from IPython.utils.log import get_logger
25 from IPython.utils.log import get_logger
26
26
27 __all__ = ['NotebookNode', 'new_code_cell', 'new_text_cell', 'new_notebook',
27 __all__ = ['NotebookNode', 'new_code_cell', 'new_text_cell', 'new_notebook',
28 'new_output', 'new_worksheet', 'parse_filename', 'new_metadata', 'new_author',
28 'new_output', 'new_worksheet', 'parse_filename', 'new_metadata', 'new_author',
29 'new_heading_cell', 'nbformat', 'nbformat_minor', 'nbformat_schema',
29 'new_heading_cell', 'nbformat', 'nbformat_minor', 'nbformat_schema',
30 'to_notebook_json', 'convert', 'validate', 'NBFormatError', 'parse_py',
30 'to_notebook_json', 'convert', 'validate', 'NBFormatError', 'parse_py',
31 'reads_json', 'writes_json', 'reads_py', 'writes_py', 'reads', 'writes', 'read',
31 'reads_json', 'writes_json', 'reads_py', 'writes_py', 'reads', 'writes', 'read',
32 'write']
32 'write']
33
33
34 current_nbformat = nbformat
34 current_nbformat = nbformat
35 current_nbformat_minor = nbformat_minor
35 current_nbformat_minor = nbformat_minor
36 current_nbformat_module = _v_latest.__name__
36 current_nbformat_module = _v_latest.__name__
37
37
38
38
39 class NBFormatError(ValueError):
39 class NBFormatError(ValueError):
40 pass
40 pass
41
41
42
42
43 def parse_py(s, **kwargs):
43 def parse_py(s, **kwargs):
44 """Parse a string into a (nbformat, string) tuple."""
44 """Parse a string into a (nbformat, string) tuple."""
45 nbf = current_nbformat
45 nbf = current_nbformat
46 nbm = current_nbformat_minor
46 nbm = current_nbformat_minor
47
47
48 pattern = r'# <nbformat>(?P<nbformat>\d+[\.\d+]*)</nbformat>'
48 pattern = r'# <nbformat>(?P<nbformat>\d+[\.\d+]*)</nbformat>'
49 m = re.search(pattern,s)
49 m = re.search(pattern,s)
50 if m is not None:
50 if m is not None:
51 digits = m.group('nbformat').split('.')
51 digits = m.group('nbformat').split('.')
52 nbf = int(digits[0])
52 nbf = int(digits[0])
53 if len(digits) > 1:
53 if len(digits) > 1:
54 nbm = int(digits[1])
54 nbm = int(digits[1])
55
55
56 return nbf, nbm, s
56 return nbf, nbm, s
57
57
58
58
59 def reads_json(nbjson, **kwargs):
59 def reads_json(nbjson, **kwargs):
60 """Read a JSON notebook from a string and return the NotebookNode
60 """Read a JSON notebook from a string and return the NotebookNode
61 object. Report if any JSON format errors are detected.
61 object. Report if any JSON format errors are detected.
62
62
63 """
63 """
64 nb = reader_reads(nbjson, **kwargs)
64 nb = reader_reads(nbjson, **kwargs)
65 nb_current = convert(nb, current_nbformat)
65 nb_current = convert(nb, current_nbformat)
66 try:
66 try:
67 validate(nb_current)
67 validate(nb_current)
68 except ValidationError as e:
68 except ValidationError as e:
69 get_logger().error("Notebook JSON is invalid: %s", e)
69 get_logger().error("Notebook JSON is invalid: %s", e)
70 return nb_current
70 return nb_current
71
71
72
72
73 def writes_json(nb, **kwargs):
73 def writes_json(nb, **kwargs):
74 """Take a NotebookNode object and write out a JSON string. Report if
74 """Take a NotebookNode object and write out a JSON string. Report if
75 any JSON format errors are detected.
75 any JSON format errors are detected.
76
76
77 """
77 """
78 try:
78 try:
79 validate(nb)
79 validate(nb)
80 except ValidationError as e:
80 except ValidationError as e:
81 get_logger().error("Notebook JSON is invalid: %s", e)
81 get_logger().error("Notebook JSON is invalid: %s", e)
82 nbjson = versions[current_nbformat].writes_json(nb, **kwargs)
82 nbjson = versions[current_nbformat].writes_json(nb, **kwargs)
83 return nbjson
83 return nbjson
84
84
85
85
86 def reads_py(s, **kwargs):
86 def reads_py(s, **kwargs):
87 """Read a .py notebook from a string and return the NotebookNode object."""
87 """Read a .py notebook from a string and return the NotebookNode object."""
88 nbf, nbm, s = parse_py(s, **kwargs)
88 nbf, nbm, s = parse_py(s, **kwargs)
89 if nbf in (2, 3):
89 if nbf in (2, 3):
90 nb = versions[nbf].to_notebook_py(s, **kwargs)
90 nb = versions[nbf].to_notebook_py(s, **kwargs)
91 else:
91 else:
92 raise NBFormatError('Unsupported PY nbformat version: %i' % nbf)
92 raise NBFormatError('Unsupported PY nbformat version: %i' % nbf)
93 return nb
93 return nb
94
94
95
95
96 def writes_py(nb, **kwargs):
96 def writes_py(nb, **kwargs):
97 # nbformat 3 is the latest format that supports py
97 # nbformat 3 is the latest format that supports py
98 return versions[3].writes_py(nb, **kwargs)
98 return versions[3].writes_py(nb, **kwargs)
99
99
100
100
101 # High level API
101 # High level API
102
102
103
103
104 def reads(s, format, **kwargs):
104 def reads(s, format='DEPRECATED', version=current_nbformat, **kwargs):
105 """Read a notebook from a string and return the NotebookNode object.
105 """Read a notebook from a string and return the NotebookNode object.
106
106
107 This function properly handles notebooks of any version. The notebook
107 This function properly handles notebooks of any version. The notebook
108 returned will always be in the current version's format.
108 returned will always be in the current version's format.
109
109
110 Parameters
110 Parameters
111 ----------
111 ----------
112 s : unicode
112 s : unicode
113 The raw unicode string to read the notebook from.
113 The raw unicode string to read the notebook from.
114 format : (u'json', u'ipynb', u'py')
115 The format that the string is in.
116
114
117 Returns
115 Returns
118 -------
116 -------
119 nb : NotebookNode
117 nb : NotebookNode
120 The notebook that was read.
118 The notebook that was read.
121 """
119 """
122 format = unicode_type(format)
120 nb = versions[version].reads_json(s, **kwargs)
123 if format == u'json' or format == u'ipynb':
121 nb = convert(nb, version)
124 return reads_json(s, **kwargs)
122 try:
125 elif format == u'py':
123 validate(nb)
126 return reads_py(s, **kwargs)
124 except ValidationError as e:
127 else:
125 get_logger().error("Notebook JSON is invalid: %s", e)
128 raise NBFormatError('Unsupported format: %s' % format)
126 return nb
129
127
130
128
131 def writes(nb, format, **kwargs):
129 def writes(nb, format='DEPRECATED', version=current_nbformat, **kwargs):
132 """Write a notebook to a string in a given format in the current nbformat version.
130 """Write a notebook to a string in a given format in the current nbformat version.
133
131
134 This function always writes the notebook in the current nbformat version.
132 This function always writes the notebook in the current nbformat version.
135
133
136 Parameters
134 Parameters
137 ----------
135 ----------
138 nb : NotebookNode
136 nb : NotebookNode
139 The notebook to write.
137 The notebook to write.
140 format : (u'json', u'ipynb', u'py')
138 version : int
141 The format to write the notebook in.
139 The nbformat version to write.
140 Used for downgrading notebooks.
142
141
143 Returns
142 Returns
144 -------
143 -------
145 s : unicode
144 s : unicode
146 The notebook string.
145 The notebook string.
147 """
146 """
148 format = unicode_type(format)
147 try:
149 if format == u'json' or format == u'ipynb':
148 validate(nb)
150 return writes_json(nb, **kwargs)
149 except ValidationError as e:
151 elif format == u'py':
150 get_logger().error("Notebook JSON is invalid: %s", e)
152 return writes_py(nb, **kwargs)
151 nb = convert(nb, version)
153 else:
152 return versions[version].writes_json(nb, **kwargs)
154 raise NBFormatError('Unsupported format: %s' % format)
155
153
156
154
157 def read(fp, format, **kwargs):
155 def read(fp, format='DEPRECATED', **kwargs):
158 """Read a notebook from a file and return the NotebookNode object.
156 """Read a notebook from a file and return the NotebookNode object.
159
157
160 This function properly handles notebooks of any version. The notebook
158 This function properly handles notebooks of any version. The notebook
161 returned will always be in the current version's format.
159 returned will always be in the current version's format.
162
160
163 Parameters
161 Parameters
164 ----------
162 ----------
165 fp : file
163 fp : file
166 Any file-like object with a read method.
164 Any file-like object with a read method.
167 format : (u'json', u'ipynb', u'py')
168 The format that the string is in.
169
165
170 Returns
166 Returns
171 -------
167 -------
172 nb : NotebookNode
168 nb : NotebookNode
173 The notebook that was read.
169 The notebook that was read.
174 """
170 """
175 return reads(fp.read(), format, **kwargs)
171 return reads(fp.read(), **kwargs)
176
172
177
173
178 def write(nb, fp, format, **kwargs):
174 def write(nb, fp, format='DEPRECATED', **kwargs):
179 """Write a notebook to a file in a given format in the current nbformat version.
175 """Write a notebook to a file in a given format in the current nbformat version.
180
176
181 This function always writes the notebook in the current nbformat version.
177 This function always writes the notebook in the current nbformat version.
182
178
183 Parameters
179 Parameters
184 ----------
180 ----------
185 nb : NotebookNode
181 nb : NotebookNode
186 The notebook to write.
182 The notebook to write.
187 fp : file
183 fp : file
188 Any file-like object with a write method.
184 Any file-like object with a write method.
189 format : (u'json', u'ipynb', u'py')
185 format : (u'json', u'ipynb', u'py')
190 The format to write the notebook in.
186 The format to write the notebook in.
191
187
192 Returns
188 Returns
193 -------
189 -------
194 s : unicode
190 s : unicode
195 The notebook string.
191 The notebook string.
196 """
192 """
197 return fp.write(writes(nb, format, **kwargs))
193 return fp.write(writes(nb, **kwargs))
198
194
199 def _convert_to_metadata():
195 def _convert_to_metadata():
200 """Convert to a notebook having notebook metadata."""
196 """Convert to a notebook having notebook metadata."""
201 import glob
197 import glob
202 for fname in glob.glob('*.ipynb'):
198 for fname in glob.glob('*.ipynb'):
203 print('Converting file:',fname)
199 print('Converting file:',fname)
204 with open(fname,'r') as f:
200 with open(fname,'r') as f:
205 nb = read(f,u'json')
201 nb = read(f,u'json')
206 md = new_metadata()
202 md = new_metadata()
207 if u'name' in nb:
203 if u'name' in nb:
208 md.name = nb.name
204 md.name = nb.name
209 del nb[u'name']
205 del nb[u'name']
210 nb.metadata = md
206 nb.metadata = md
211 with open(fname,'w') as f:
207 with open(fname,'w') as f:
212 write(nb, f, u'json')
208 write(nb, f, u'json')
213
209
@@ -1,36 +1,41 b''
1 """
1 """
2 Contains tests class for current.py
2 Contains tests class for current.py
3 """
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2013 The IPython Development Team
6 #
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
10
4
11 #-----------------------------------------------------------------------------
5 # Copyright (c) IPython Development Team.
12 # Imports
6 # Distributed under the terms of the Modified BSD License.
13 #-----------------------------------------------------------------------------
7
8 import io
9 import json
10 import tempfile
14
11
15 from .base import TestsBase
12 from .base import TestsBase
16
13
17 from ..reader import get_version
14 from ..reader import get_version
18 from ..current import read, current_nbformat
15 from ..current import read, current_nbformat, validate, writes
19
16
20 #-----------------------------------------------------------------------------
21 # Classes and functions
22 #-----------------------------------------------------------------------------
23
17
24 class TestCurrent(TestsBase):
18 class TestCurrent(TestsBase):
25
19
26 def test_read(self):
20 def test_read(self):
27 """Can older notebooks be opened and automatically converted to the current
21 """Can older notebooks be opened and automatically converted to the current
28 nbformat?"""
22 nbformat?"""
29
23
30 # Open a version 2 notebook.
24 # Open a version 2 notebook.
31 with self.fopen(u'test2.ipynb', u'r') as f:
25 with self.fopen(u'test2.ipynb', u'r') as f:
32 nb = read(f, u'json')
26 nb = read(f)
33
27
34 # Check that the notebook was upgraded to the latest version automatically.
28 # Check that the notebook was upgraded to the latest version automatically.
35 (major, minor) = get_version(nb)
29 (major, minor) = get_version(nb)
36 self.assertEqual(major, current_nbformat)
30 self.assertEqual(major, current_nbformat)
31
32 def test_write_downgrade_2(self):
33 """dowgrade a v3 notebook to v2"""
34 # Open a version 3 notebook.
35 with self.fopen(u'test3.ipynb', 'r') as f:
36 nb = read(f, u'json')
37
38 jsons = writes(nb, version=2)
39 nb2 = json.loads(jsons)
40 (major, minor) = get_version(nb2)
41 self.assertEqual(major, 2)
General Comments 0
You need to be logged in to leave comments. Login now