##// END OF EJS Templates
address review from takluyver...
MinRK -
Show More
@@ -57,7 +57,7 b' casper.notebook_test(function () {'
57 this.trigger_keydown('b'); // new cell below
57 this.trigger_keydown('b'); // new cell below
58 this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell below code cell');
58 this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell below code cell');
59 this.trigger_keydown('a'); // new cell above
59 this.trigger_keydown('a'); // new cell above
60 this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'a; inserts a code cell below code cell');
60 this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'a; inserts a code cell above code cell');
61 });
61 });
62
62
63 this.thenEvaluate(function() {
63 this.thenEvaluate(function() {
@@ -72,6 +72,6 b' casper.notebook_test(function () {'
72 this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'a; inserts a raw cell above raw cell');
72 this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'a; inserts a raw cell above raw cell');
73 this.trigger_keydown('y'); // switch it to code for the next test
73 this.trigger_keydown('y'); // switch it to code for the next test
74 this.trigger_keydown('b'); // new cell below
74 this.trigger_keydown('b'); // new cell below
75 this.test.assertEquals(this.get_cell(3).cell_type, 'raw', 'b; inserts a raw cell above raw cell');
75 this.test.assertEquals(this.get_cell(3).cell_type, 'raw', 'b; inserts a raw cell below raw cell');
76 });
76 });
77 });
77 });
@@ -72,14 +72,9 b' class ExtractOutputPreprocessor(Preprocessor):'
72 else:
72 else:
73 data = data.encode("UTF-8")
73 data = data.encode("UTF-8")
74
74
75 # Build an output name
75 ext = guess_extension(mime_type)
76 # filthy hack while we have some mimetype output, and some not
76 if ext is None:
77 if '/' in mime_type:
77 ext = '.' + mime_type.rsplit('/')[-1]
78 ext = guess_extension(mime_type)
79 if ext is None:
80 ext = '.' + mime_type.rsplit('/')[-1]
81 else:
82 ext = '.' + mime_type
83
78
84 filename = self.output_filename_template.format(
79 filename = self.output_filename_template.format(
85 unique_key=unique_key,
80 unique_key=unique_key,
@@ -87,10 +82,10 b' class ExtractOutputPreprocessor(Preprocessor):'
87 index=index,
82 index=index,
88 extension=ext)
83 extension=ext)
89
84
90 #On the cell, make the figure available via
85 # On the cell, make the figure available via
91 # cell.outputs[i].metadata.filenames['mime/type']
86 # cell.outputs[i].metadata.filenames['mime/type']
92 # Where
87 # where
93 # cell.outputs[i].data['mime/type' contains the data
88 # cell.outputs[i].data['mime/type'] contains the data
94 if output_files_dir is not None:
89 if output_files_dir is not None:
95 filename = os.path.join(output_files_dir, filename)
90 filename = os.path.join(output_files_dir, filename)
96 out.metadata.setdefault('filenames', {})
91 out.metadata.setdefault('filenames', {})
@@ -1,17 +1,9 b''
1 """Module containing a preprocessor that converts outputs in the notebook from
1 """Module containing a preprocessor that converts outputs in the notebook from
2 one format to another.
2 one format to another.
3 """
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
4
12 #-----------------------------------------------------------------------------
5 # Copyright (c) IPython Development Team.
13 # Imports
6 # Distributed under the terms of the Modified BSD License.
14 #-----------------------------------------------------------------------------
15
7
16 import base64
8 import base64
17 import io
9 import io
@@ -25,15 +17,8 b' from IPython.utils.traitlets import Unicode'
25 from .convertfigures import ConvertFiguresPreprocessor
17 from .convertfigures import ConvertFiguresPreprocessor
26
18
27
19
28 #-----------------------------------------------------------------------------
29 # Constants
30 #-----------------------------------------------------------------------------
31
32 INKSCAPE_APP = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
20 INKSCAPE_APP = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
33
21
34 #-----------------------------------------------------------------------------
35 # Classes
36 #-----------------------------------------------------------------------------
37
22
38 class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):
23 class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):
39 """
24 """
@@ -41,7 +26,7 b' class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):'
41 """
26 """
42
27
43 def _from_format_default(self):
28 def _from_format_default(self):
44 return 'svg'
29 return 'image/svg+xml'
45 def _to_format_default(self):
30 def _to_format_default(self):
46 return 'application/pdf'
31 return 'application/pdf'
47
32
@@ -16,16 +16,16 b' class PreprocessorTestsBase(TestsBase):'
16 def build_notebook(self):
16 def build_notebook(self):
17 """Build a notebook in memory for use with preprocessor tests"""
17 """Build a notebook in memory for use with preprocessor tests"""
18
18
19 outputs = [nbformat.new_output(output_type="stream", name="stdout", text="a"),
19 outputs = [
20 nbformat.new_output(output_type="display_data", data={'text/plain': 'b'}),
20 nbformat.new_output("stream", name="stdout", text="a"),
21 nbformat.new_output(output_type="stream", name="stdout", text="c"),
21 nbformat.new_output("display_data", data={'text/plain': 'b'}),
22 nbformat.new_output(output_type="stream", name="stdout", text="d"),
22 nbformat.new_output("stream", name="stdout", text="c"),
23 nbformat.new_output(output_type="stream", name="stderr", text="e"),
23 nbformat.new_output("stream", name="stdout", text="d"),
24 nbformat.new_output(output_type="stream", name="stderr", text="f"),
24 nbformat.new_output("stream", name="stderr", text="e"),
25 nbformat.new_output(output_type="display_data", data={'image/png': 'Zw=='})] # g
25 nbformat.new_output("stream", name="stderr", text="f"),
26 out = nbformat.new_output(output_type="display_data")
26 nbformat.new_output("display_data", data={'image/png': 'Zw=='}), # g
27 out.data['application/pdf'] = 'aA=='
27 nbformat.new_output("display_data", data={'application/pdf': 'aA=='}), # h
28 outputs.append(out)
28 ]
29
29
30 cells=[nbformat.new_code_cell(source="$ e $", execution_count=1, outputs=outputs),
30 cells=[nbformat.new_code_cell(source="$ e $", execution_count=1, outputs=outputs),
31 nbformat.new_markdown_cell(source="$ e $")]
31 nbformat.new_markdown_cell(source="$ e $")]
@@ -47,18 +47,18 b' class TestExecute(PreprocessorTestsBase):'
47 def assert_notebooks_equal(self, expected, actual):
47 def assert_notebooks_equal(self, expected, actual):
48 expected_cells = expected['cells']
48 expected_cells = expected['cells']
49 actual_cells = actual['cells']
49 actual_cells = actual['cells']
50 assert len(expected_cells) == len(actual_cells)
50 self.assertEqual(len(expected_cells), len(actual_cells))
51
51
52 for expected_cell, actual_cell in zip(expected_cells, actual_cells):
52 for expected_cell, actual_cell in zip(expected_cells, actual_cells):
53 expected_outputs = expected_cell.get('outputs', [])
53 expected_outputs = expected_cell.get('outputs', [])
54 actual_outputs = actual_cell.get('outputs', [])
54 actual_outputs = actual_cell.get('outputs', [])
55 normalized_expected_outputs = list(map(self.normalize_output, expected_outputs))
55 normalized_expected_outputs = list(map(self.normalize_output, expected_outputs))
56 normalized_actual_outputs = list(map(self.normalize_output, actual_outputs))
56 normalized_actual_outputs = list(map(self.normalize_output, actual_outputs))
57 assert normalized_expected_outputs == normalized_actual_outputs
57 self.assertEqual(normalized_expected_outputs, normalized_actual_outputs)
58
58
59 expected_execution_count = expected_cell.get('execution_count', None)
59 expected_execution_count = expected_cell.get('execution_count', None)
60 actual_execution_count = actual_cell.get('execution_count', None)
60 actual_execution_count = actual_cell.get('execution_count', None)
61 assert expected_execution_count == actual_execution_count
61 self.assertEqual(expected_execution_count, actual_execution_count)
62
62
63
63
64 def build_preprocessor(self):
64 def build_preprocessor(self):
@@ -10,7 +10,6 b' from ..extractoutput import ExtractOutputPreprocessor'
10 class TestExtractOutput(PreprocessorTestsBase):
10 class TestExtractOutput(PreprocessorTestsBase):
11 """Contains test functions for extractoutput.py"""
11 """Contains test functions for extractoutput.py"""
12
12
13
14 def build_preprocessor(self):
13 def build_preprocessor(self):
15 """Make an instance of a preprocessor"""
14 """Make an instance of a preprocessor"""
16 preprocessor = ExtractOutputPreprocessor()
15 preprocessor = ExtractOutputPreprocessor()
@@ -18,11 +17,9 b' class TestExtractOutput(PreprocessorTestsBase):'
18 preprocessor.enabled = True
17 preprocessor.enabled = True
19 return preprocessor
18 return preprocessor
20
19
21
22 def test_constructor(self):
20 def test_constructor(self):
23 """Can a ExtractOutputPreprocessor be constructed?"""
21 """Can a ExtractOutputPreprocessor be constructed?"""
24 self.build_preprocessor()
22 self.build_preprocessor()
25
26
23
27 def test_output(self):
24 def test_output(self):
28 """Test the output of the ExtractOutputPreprocessor"""
25 """Test the output of the ExtractOutputPreprocessor"""
@@ -32,30 +29,30 b' class TestExtractOutput(PreprocessorTestsBase):'
32 nb, res = preprocessor(nb, res)
29 nb, res = preprocessor(nb, res)
33 # Check if text was extracted.
30 # Check if text was extracted.
34 output = nb.cells[0].outputs[1]
31 output = nb.cells[0].outputs[1]
35 assert 'filenames' in output.metadata
32 self.assertIn('filenames', output.metadata)
36 assert 'text/plain' in output.metadata.filenames
33 self.assertIn('text/plain', output.metadata.filenames)
37 text_filename = output.metadata.filenames['text/plain']
34 text_filename = output.metadata.filenames['text/plain']
38
35
39 # Check if png was extracted.
36 # Check if png was extracted.
40 output = nb.cells[0].outputs[6]
37 output = nb.cells[0].outputs[6]
41 assert 'filenames' in output.metadata
38 self.assertIn('filenames', output.metadata)
42 assert 'image/png' in output.metadata.filenames
39 self.assertIn('image/png', output.metadata.filenames)
43 png_filename = output.metadata.filenames['image/png']
40 png_filename = output.metadata.filenames['image/png']
44
41
45 # Check that pdf was extracted
42 # Check that pdf was extracted
46 output = nb.cells[0].outputs[7]
43 output = nb.cells[0].outputs[7]
47 assert 'filenames' in output.metadata
44 self.assertIn('filenames', output.metadata)
48 assert 'application/pdf' in output.metadata.filenames
45 self.assertIn('application/pdf', output.metadata.filenames)
49 pdf_filename = output.metadata.filenames['application/pdf']
46 pdf_filename = output.metadata.filenames['application/pdf']
50
47
51 # Verify text output
48 # Verify text output
52 assert text_filename in res['outputs']
49 self.assertIn(text_filename, res['outputs'])
53 self.assertEqual(res['outputs'][text_filename], b'b')
50 self.assertEqual(res['outputs'][text_filename], b'b')
54
51
55 # Verify png output
52 # Verify png output
56 assert png_filename in res['outputs']
53 self.assertIn(png_filename, res['outputs'])
57 self.assertEqual(res['outputs'][png_filename], b'g')
54 self.assertEqual(res['outputs'][png_filename], b'g')
58
55
59 # Verify pdf output
56 # Verify pdf output
60 assert pdf_filename in res['outputs']
57 self.assertIn(pdf_filename, res['outputs'])
61 self.assertEqual(res['outputs'][pdf_filename], b'h')
58 self.assertEqual(res['outputs'][pdf_filename], b'h')
@@ -39,10 +39,10 b' class Testsvg2pdf(PreprocessorTestsBase):'
39 </svg>"""
39 </svg>"""
40
40
41 def build_notebook(self):
41 def build_notebook(self):
42 """Build a reveal slides notebook in memory for use with tests.
42 """Build a reveal slides notebook in memory for use with tests.
43 Overrides base in PreprocessorTestsBase"""
43 Overrides base in PreprocessorTestsBase"""
44
44
45 outputs = [nbformat.new_output(output_type="svg", output_svg=self.simple_svg)]
45 outputs = [nbformat.new_output(output_type="image/svg+xml", output_svg=self.simple_svg)]
46
46
47 slide_metadata = {'slideshow' : {'slide_type': 'slide'}}
47 slide_metadata = {'slideshow' : {'slide_type': 'slide'}}
48 subslide_metadata = {'slideshow' : {'slide_type': 'subslide'}}
48 subslide_metadata = {'slideshow' : {'slide_type': 'subslide'}}
@@ -71,4 +71,4 b' class Testsvg2pdf(PreprocessorTestsBase):'
71 res = self.build_resources()
71 res = self.build_resources()
72 preprocessor = self.build_preprocessor()
72 preprocessor = self.build_preprocessor()
73 nb, res = preprocessor(nb, res)
73 nb, res = preprocessor(nb, res)
74 assert 'svg' in nb.cells[0].outputs[0]
74 self.assertIn('application/pdf', nb.cells[0].outputs[0])
@@ -44,8 +44,7 b' def convert(nb, to_version):'
44 # Convert and make sure version changed during conversion.
44 # Convert and make sure version changed during conversion.
45 converted = convert_function(nb)
45 converted = convert_function(nb)
46 if converted.get('nbformat', 1) == version:
46 if converted.get('nbformat', 1) == version:
47 raise ValueError("Cannot convert notebook from v%d to v%d. Operation" \
47 raise ValueError("Failed to convert notebook from v%d to v%d." % (version, step_version))
48 "failed silently." % (version, step_version))
49
48
50 # Recursively convert until target version is reached.
49 # Recursively convert until target version is reached.
51 return convert(converted, to_version)
50 return convert(converted, to_version)
@@ -180,9 +180,6 b' class NotebookNotary(LoggingConfigurable):'
180
180
181 This function is the inverse of check_cells
181 This function is the inverse of check_cells
182 """
182 """
183 if not nb['cells']:
184 # nothing to mark if there are no cells
185 return
186 for cell in nb['cells']:
183 for cell in nb['cells']:
187 if cell['cell_type'] == 'code':
184 if cell['cell_type'] == 'code':
188 cell['metadata']['trusted'] = trusted
185 cell['metadata']['trusted'] = trusted
@@ -224,8 +221,6 b' class NotebookNotary(LoggingConfigurable):'
224
221
225 This function is the inverse of mark_cells.
222 This function is the inverse of mark_cells.
226 """
223 """
227 if not nb['cells']:
228 return True
229 trusted = True
224 trusted = True
230 for cell in nb['cells']:
225 for cell in nb['cells']:
231 if cell['cell_type'] != 'code':
226 if cell['cell_type'] != 'code':
@@ -28,10 +28,7 b' class NotebookNode(Struct):'
28
28
29 def from_dict(d):
29 def from_dict(d):
30 if isinstance(d, dict):
30 if isinstance(d, dict):
31 newd = NotebookNode()
31 return NotebookNode({k:from_dict(v) for k,v in d.items()})
32 for k,v in d.items():
33 newd[k] = from_dict(v)
34 return newd
35 elif isinstance(d, (tuple, list)):
32 elif isinstance(d, (tuple, list)):
36 return [from_dict(i) for i in d]
33 return [from_dict(i) for i in d]
37 else:
34 else:
@@ -41,17 +38,19 b' def from_dict(d):'
41 def new_output(output_type, data=None, **kwargs):
38 def new_output(output_type, data=None, **kwargs):
42 """Create a new output, to go in the ``cell.outputs`` list of a code cell."""
39 """Create a new output, to go in the ``cell.outputs`` list of a code cell."""
43 output = NotebookNode(output_type=output_type)
40 output = NotebookNode(output_type=output_type)
44 output.update(from_dict(kwargs))
45 if data is not None:
46 output.data = from_dict(data)
47
41
48 # populate defaults:
42 # populate defaults:
49 if output_type == 'stream':
43 if output_type == 'stream':
50 output.setdefault('name', 'stdout')
44 output.name = u'stdout'
51 output.setdefault('text', '')
45 output.text = u''
52 elif output_type in {'execute_result', 'display_data'}:
46 elif output_type in {'execute_result', 'display_data'}:
53 output.setdefault('metadata', NotebookNode())
47 output.metadata = NotebookNode()
54 output.setdefault('data', NotebookNode())
48 output.data = NotebookNode()
49 # load from args:
50 output.update(from_dict(kwargs))
51 if data is not None:
52 output.data = from_dict(data)
53 # validate
55 validate(output, output_type)
54 validate(output, output_type)
56 return output
55 return output
57
56
@@ -79,7 +78,6 b' def output_from_msg(msg):'
79 data=content['data'],
78 data=content['data'],
80 execution_count=content['execution_count'],
79 execution_count=content['execution_count'],
81 )
80 )
82
83 elif msg_type == 'stream':
81 elif msg_type == 'stream':
84 return new_output(output_type=msg_type,
82 return new_output(output_type=msg_type,
85 name=content['name'],
83 name=content['name'],
@@ -102,40 +100,50 b' def output_from_msg(msg):'
102
100
103 def new_code_cell(source='', **kwargs):
101 def new_code_cell(source='', **kwargs):
104 """Create a new code cell"""
102 """Create a new code cell"""
105 cell = NotebookNode(cell_type='code', source=source)
103 cell = NotebookNode(
104 cell_type='code',
105 metadata=NotebookNode(),
106 execution_count=None,
107 source=source,
108 outputs=[],
109 )
106 cell.update(from_dict(kwargs))
110 cell.update(from_dict(kwargs))
107 cell.setdefault('metadata', NotebookNode())
108 cell.setdefault('source', '')
109 cell.setdefault('execution_count', None)
110 cell.setdefault('outputs', [])
111
111
112 validate(cell, 'code_cell')
112 validate(cell, 'code_cell')
113 return cell
113 return cell
114
114
115 def new_markdown_cell(source='', **kwargs):
115 def new_markdown_cell(source='', **kwargs):
116 """Create a new markdown cell"""
116 """Create a new markdown cell"""
117 cell = NotebookNode(cell_type='markdown', source=source)
117 cell = NotebookNode(
118 cell_type='markdown',
119 source=source,
120 metadata=NotebookNode(),
121 )
118 cell.update(from_dict(kwargs))
122 cell.update(from_dict(kwargs))
119 cell.setdefault('metadata', NotebookNode())
120
123
121 validate(cell, 'markdown_cell')
124 validate(cell, 'markdown_cell')
122 return cell
125 return cell
123
126
124 def new_raw_cell(source='', **kwargs):
127 def new_raw_cell(source='', **kwargs):
125 """Create a new raw cell"""
128 """Create a new raw cell"""
126 cell = NotebookNode(cell_type='raw', source=source)
129 cell = NotebookNode(
130 cell_type='raw',
131 source=source,
132 metadata=NotebookNode(),
133 )
127 cell.update(from_dict(kwargs))
134 cell.update(from_dict(kwargs))
128 cell.setdefault('metadata', NotebookNode())
129
135
130 validate(cell, 'raw_cell')
136 validate(cell, 'raw_cell')
131 return cell
137 return cell
132
138
133 def new_notebook(**kwargs):
139 def new_notebook(**kwargs):
134 """Create a new notebook"""
140 """Create a new notebook"""
135 nb = from_dict(kwargs)
141 nb = NotebookNode(
136 nb.nbformat = nbformat
142 nbformat=nbformat,
137 nb.nbformat_minor = nbformat_minor
143 nbformat_minor=nbformat_minor,
138 nb.setdefault('cells', [])
144 metadata=NotebookNode(),
139 nb.setdefault('metadata', NotebookNode())
145 cells=[],
146 )
147 nb.update(from_dict(kwargs))
140 validate(nb)
148 validate(nb)
141 return nb
149 return nb
@@ -3,32 +3,7 b''
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 IPython.utils import py3compat
6 from IPython.utils.py3compat import string_types, cast_unicode_py2
7 from IPython.utils.py3compat import unicode_type, string_types
8
9 # output keys that are likely to have multiline values
10 _multiline_outputs = {
11 'text/plain',
12 'text/html',
13 'image/svg+xml',
14 'text/latex',
15 'application/javascript',
16 }
17
18
19 # FIXME: workaround for old splitlines()
20 def _join_lines(lines):
21 """join lines that have been written by splitlines()
22
23 Has logic to protect against `splitlines()`, which
24 should have been `splitlines(True)`
25 """
26 if lines and lines[0].endswith(('\n', '\r')):
27 # created by splitlines(True)
28 return u''.join(lines)
29 else:
30 # created by splitlines()
31 return u'\n'.join(lines)
32
7
33
8
34 def rejoin_lines(nb):
9 def rejoin_lines(nb):
@@ -43,17 +18,17 b' def rejoin_lines(nb):'
43 """
18 """
44 for cell in nb.cells:
19 for cell in nb.cells:
45 if 'source' in cell and isinstance(cell.source, list):
20 if 'source' in cell and isinstance(cell.source, list):
46 cell.source = _join_lines(cell.source)
21 cell.source = ''.join(cell.source)
47 if cell.get('cell_type', None) == 'code':
22 if cell.get('cell_type', None) == 'code':
48 for output in cell.get('outputs', []):
23 for output in cell.get('outputs', []):
49 output_type = output.get('output_type', '')
24 output_type = output.get('output_type', '')
50 if output_type in {'execute_result', 'display_data'}:
25 if output_type in {'execute_result', 'display_data'}:
51 for key, value in output.get('data', {}).items():
26 for key, value in output.get('data', {}).items():
52 if key != 'application/json' and isinstance(value, list):
27 if key != 'application/json' and isinstance(value, list):
53 output.data[key] = _join_lines(value)
28 output.data[key] = ''.join(value)
54 elif output_type:
29 elif output_type:
55 if isinstance(output.get('text', ''), list):
30 if isinstance(output.get('text', ''), list):
56 output.text = _join_lines(output.text)
31 output.text = ''.join(output.text)
57 return nb
32 return nb
58
33
59
34
@@ -103,9 +78,7 b' class NotebookReader(object):'
103
78
104 def read(self, fp, **kwargs):
79 def read(self, fp, **kwargs):
105 """Read a notebook from a file like object"""
80 """Read a notebook from a file like object"""
106 nbs = fp.read()
81 nbs = cast_unicode_py2(fp.read())
107 if not py3compat.PY3 and not isinstance(nbs, unicode_type):
108 nbs = py3compat.str_to_unicode(nbs)
109 return self.reads(nbs, **kwargs)
82 return self.reads(nbs, **kwargs)
110
83
111
84
@@ -118,8 +91,5 b' class NotebookWriter(object):'
118
91
119 def write(self, nb, fp, **kwargs):
92 def write(self, nb, fp, **kwargs):
120 """Write a notebook to a file like object"""
93 """Write a notebook to a file like object"""
121 nbs = self.writes(nb,**kwargs)
94 nbs = cast_unicode_py2(self.writes(nb, **kwargs))
122 if not py3compat.PY3 and not isinstance(nbs, unicode_type):
123 # this branch is likely only taken for JSON on Python 2
124 nbs = py3compat.str_to_unicode(nbs)
125 return fp.write(nbs)
95 return fp.write(nbs)
@@ -49,6 +49,14 b' At the highest level, a Jupyter notebook is a dictionary with a few keys:'
49 ],
49 ],
50 }
50 }
51
51
52 Some fields, such as code input and text output, are characteristically multi-line strings.
53 When these fields are written to disk, they **may** be written as a list of strings,
54 which should be joined with ``''`` when reading back into memory.
55 In programmatic APIs for working with notebooks (Python, Javascript),
56 these are always re-joined into the original multi-line string.
57 If you intend to work with notebook files directly,
58 you must allow multi-line string fields to be either a string or list of strings.
59
52
60
53 Cell Types
61 Cell Types
54 ==========
62 ==========
@@ -82,7 +90,7 b' as defined in `GitHub-flavored markdown`_, and implemented in marked_.'
82 "source" : ["some *markdown*"],
90 "source" : ["some *markdown*"],
83 }
91 }
84
92
85 .. versionchanged:: 4.0
93 .. versionchanged:: nbformat 4.0
86
94
87 Heading cells have been removed, in favor of simple headings in markdown.
95 Heading cells have been removed, in favor of simple headings in markdown.
88
96
@@ -91,8 +99,8 b' Code cells'
91 ----------
99 ----------
92
100
93 Code cells are the primary content of Jupyter notebooks.
101 Code cells are the primary content of Jupyter notebooks.
94 They contain source code int e language of the document's associated kernel,
102 They contain source code in the language of the document's associated kernel,
95 and a list of outputs associated with executing.
103 and a list of outputs associated with executing that code.
96 They also have an execution_count, which must be an integer or ``null``.
104 They also have an execution_count, which must be an integer or ``null``.
97
105
98 .. sourcecode:: python
106 .. sourcecode:: python
@@ -112,11 +120,11 b' They also have an execution_count, which must be an integer or ``null``.'
112 }],
120 }],
113 }
121 }
114
122
115 .. versionchanged:: 4.0
123 .. versionchanged:: nbformat 4.0
116
124
117 ``input`` was renamed to ``source``, for consistency among cell types.
125 ``input`` was renamed to ``source``, for consistency among cell types.
118
126
119 .. versionchanged:: 4.0
127 .. versionchanged:: nbformat 4.0
120
128
121 ``prompt_number`` renamed to ``execution_count``
129 ``prompt_number`` renamed to ``execution_count``
122
130
@@ -141,7 +149,7 b' stream output'
141 "data" : ["multiline stream text"],
149 "data" : ["multiline stream text"],
142 }
150 }
143
151
144 .. versionchanged:: 4.0
152 .. versionchanged:: nbformat 4.0
145
153
146 The keys ``stream`` and ``text`` were changed to ``name`` and ``data`` to match
154 The keys ``stream`` and ``text`` were changed to ``name`` and ``data`` to match
147 the stream message specification.
155 the stream message specification.
@@ -176,11 +184,11 b' The metadata of these messages may be keyed by mime-type as well.'
176 }
184 }
177
185
178
186
179 .. versionchanged:: 4.0
187 .. versionchanged:: nbformat 4.0
180
188
181 ``application/json`` output is no longer double-serialized into a string.
189 ``application/json`` output is no longer double-serialized into a string.
182
190
183 .. versionchanged:: 4.0
191 .. versionchanged:: nbformat 4.0
184
192
185 mime-types are used for keys, instead of a combination of short names (``text``)
193 mime-types are used for keys, instead of a combination of short names (``text``)
186 and mime-types, and are stored in a ``data`` key, rather than the top-level.
194 and mime-types, and are stored in a ``data`` key, rather than the top-level.
@@ -193,13 +201,13 b' execute_result'
193 Results of executing a cell (as created by ``displayhook`` in Python)
201 Results of executing a cell (as created by ``displayhook`` in Python)
194 are stored in ``execute_result`` outputs.
202 are stored in ``execute_result`` outputs.
195 `execute_result` outputs are identical to ``display_data``,
203 `execute_result` outputs are identical to ``display_data``,
196 adding only a ``prompt_number`` field, which must be an integer.
204 adding only a ``execution_count`` field, which must be an integer.
197
205
198 .. sourcecode:: python
206 .. sourcecode:: python
199
207
200 {
208 {
201 "output_type" : "execute_result",
209 "output_type" : "execute_result",
202 "execute_result": 42,
210 "execution_count": 42,
203 "data" : {
211 "data" : {
204 "text/plain" : ["multiline text data"],
212 "text/plain" : ["multiline text data"],
205 "image/png": ["base64-encoded-png-data"],
213 "image/png": ["base64-encoded-png-data"],
@@ -216,11 +224,11 b' adding only a ``prompt_number`` field, which must be an integer.'
216 },
224 },
217 }
225 }
218
226
219 .. versionchanged:: 4.0
227 .. versionchanged:: nbformat 4.0
220
228
221 ``pyout`` renamed to ``execute_result``
229 ``pyout`` renamed to ``execute_result``
222
230
223 .. versionchanged:: 4.0
231 .. versionchanged:: nbformat 4.0
224
232
225 ``prompt_number`` renamed to ``execution_count``
233 ``prompt_number`` renamed to ``execution_count``
226
234
@@ -241,7 +249,7 b' Failed execution may show a traceback'
241 'traceback' : list,
249 'traceback' : list,
242 }
250 }
243
251
244 .. versionchanged:: 4.0
252 .. versionchanged:: nbformat 4.0
245
253
246 ``pyerr`` renamed to ``error``
254 ``pyerr`` renamed to ``error``
247
255
@@ -295,8 +303,8 b' The following metadata keys are defined at the notebook level:'
295 =========== =============== ==============
303 =========== =============== ==============
296 Key Value Interpretation
304 Key Value Interpretation
297 =========== =============== ==============
305 =========== =============== ==============
298 kernelspec dict A kernel specification. More detail :ref:`here <kernelspecs>`
306 kernelspec dict A :ref:`kernel specification <kernelspecs>`
299 signature str A hashed signature of the notebook
307 signature str A hashed :ref:`signature <notebook_security>` of the notebook
300 =========== =============== ==============
308 =========== =============== ==============
301
309
302
310
General Comments 0
You need to be logged in to leave comments. Login now