##// END OF EJS Templates
first complete pass on v4...
MinRK -
Show More
@@ -0,0 +1,78 b''
1 """Python API for composing notebook elements
2
3 The Python representation of a notebook is a nested structure of
4 dictionary subclasses that support attribute access
5 (IPython.utils.ipstruct.Struct). The functions in this module are merely
6 helpers to build the structs in the right form.
7 """
8
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
11
12 import pprint
13 import uuid
14
15 from IPython.utils.ipstruct import Struct
16 from IPython.utils.py3compat import cast_unicode, unicode_type
17
18 from .validator import isvalid, validate
19 from .nbbase import nbformat, nbformat_minor, from_dict, NotebookNode
20
21 def new_output(output_type, mime_bundle=None, **kwargs):
22 """Create a new output, to go in the ``cell.outputs`` list of a code cell."""
23 output = NotebookNode(output_type=output_type, **kwargs)
24 if mime_bundle:
25 output.update(mime_bundle)
26 # populate defaults:
27 output.setdefault('metadata', NotebookNode())
28 if output_type == 'stream':
29 output.setdefault('stream', 'stdout')
30 output.setdefault('text', '')
31 validate(output, output_type)
32 return output
33
34 def new_code_cell(source='', **kwargs):
35 """Create a new code cell"""
36 cell = NotebookNode(cell_type='code', source=source, **kwargs)
37 cell.setdefault('metadata', NotebookNode())
38 cell.setdefault('source', '')
39 cell.setdefault('prompt_number', None)
40 cell.setdefault('outputs', [])
41
42 validate(cell, 'code_cell')
43 return cell
44
45 def new_markdown_cell(source='', **kwargs):
46 """Create a new markdown cell"""
47 cell = NotebookNode(cell_type='markdown', source=source, **kwargs)
48 cell.setdefault('metadata', NotebookNode())
49
50 validate(cell, 'markdown_cell')
51 return cell
52
53 def new_heading_cell(source='', **kwargs):
54 """Create a new heading cell"""
55 cell = NotebookNode(cell_type='heading', source=source, **kwargs)
56 cell.setdefault('metadata', NotebookNode())
57 cell.setdefault('level', 1)
58
59 validate(cell, 'heading_cell')
60 return cell
61
62 def new_raw_cell(source='', **kwargs):
63 """Create a new raw cell"""
64 cell = NotebookNode(cell_type='raw', source=source, **kwargs)
65 cell.setdefault('metadata', NotebookNode())
66
67 validate(cell, 'raw_cell')
68 return cell
69
70 def new_notebook(**kwargs):
71 """Create a new notebook"""
72 nb = NotebookNode(**kwargs)
73 nb.nbformat = nbformat
74 nb.nbformat_minor = nbformat_minor
75 nb.setdefault('cells', [])
76 nb.setdefault('metadata', NotebookNode())
77 validate(nb)
78 return nb
@@ -0,0 +1,105 b''
1 # coding: utf-8
2 """Tests for the Python API for composing notebook elements"""
3
4 import nose.tools as nt
5
6 from ..validator import isvalid, validate, ValidationError
7 from ..compose import (
8 NotebookNode, nbformat,
9 new_code_cell, new_heading_cell, new_markdown_cell, new_notebook,
10 new_output, new_raw_cell,
11 )
12
13 def test_empty_notebook():
14 nb = new_notebook()
15 nt.assert_equal(nb.cells, [])
16 nt.assert_equal(nb.metadata, NotebookNode())
17 nt.assert_equal(nb.nbformat, nbformat)
18
19 def test_empty_markdown_cell():
20 cell = new_markdown_cell()
21 nt.assert_equal(cell.cell_type, 'markdown')
22 nt.assert_equal(cell.source, '')
23
24 def test_markdown_cell():
25 cell = new_markdown_cell(u'* Søme markdown')
26 nt.assert_equal(cell.source, u'* Søme markdown')
27
28 def test_empty_raw_cell():
29 cell = new_raw_cell()
30 nt.assert_equal(cell.cell_type, u'raw')
31 nt.assert_equal(cell.source, '')
32
33 def test_raw_cell():
34 cell = new_raw_cell('hi')
35 nt.assert_equal(cell.source, u'hi')
36
37 def test_empty_heading_cell():
38 cell = new_heading_cell()
39 nt.assert_equal(cell.cell_type, u'heading')
40 nt.assert_equal(cell.source, '')
41 nt.assert_equal(cell.level, 1)
42
43 def test_heading_cell():
44 cell = new_heading_cell(u'hi', level=2)
45 nt.assert_equal(cell.source, u'hi')
46 nt.assert_equal(cell.level, 2)
47
48 def test_empty_code_cell():
49 cell = new_code_cell('hi')
50 nt.assert_equal(cell.cell_type, 'code')
51 nt.assert_equal(cell.source, u'hi')
52
53 def test_empty_display_data():
54 output = new_output('display_data')
55 nt.assert_equal(output.output_type, 'display_data')
56
57 def test_empty_stream():
58 output = new_output('stream', stream='stdout', text='')
59 nt.assert_equal(output.output_type, 'stream')
60
61 def test_empty_execute_result():
62 output = new_output('execute_result', prompt_number=1)
63 nt.assert_equal(output.output_type, 'execute_result')
64
65 mimebundle = {
66 'text/plain': "some text",
67 "application/json": {
68 "key": "value"
69 },
70 "image/svg+xml": 'ABCDEF',
71 "application/octet-stream": 'ABC-123',
72 "application/vnd.foo+bar": "Some other stuff",
73 }
74
75 def test_display_data():
76 output = new_output('display_data', mimebundle)
77 for key, expected in mimebundle.items():
78 nt.assert_equal(output[key], expected)
79
80 def test_execute_result():
81 output = new_output('execute_result', mimebundle, prompt_number=10)
82 nt.assert_equal(output.prompt_number, 10)
83 for key, expected in mimebundle.items():
84 nt.assert_equal(output[key], expected)
85
86 def test_error():
87 o = new_output(output_type=u'error', ename=u'NameError',
88 evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2']
89 )
90 nt.assert_equal(o.output_type, u'error')
91 nt.assert_equal(o.ename, u'NameError')
92 nt.assert_equal(o.evalue, u'Name not found')
93 nt.assert_equal(o.traceback, [u'frame 0', u'frame 1', u'frame 2'])
94
95 def test_code_cell_with_outputs():
96 cell = new_code_cell(prompt_number=10, outputs=[
97 new_output('display_data', mimebundle),
98 new_output('stream', text='hello'),
99 new_output('execute_result', mimebundle, prompt_number=10),
100 ])
101 nt.assert_equal(cell.prompt_number, 10)
102 nt.assert_equal(len(cell.outputs), 3)
103 er = cell.outputs[-1]
104 nt.assert_equal(er.prompt_number, 10)
105 nt.assert_equal(er['output_type'], 'execute_result')
@@ -0,0 +1,126 b''
1 """Tests for nbformat validation"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import io
7 import os
8
9 import nose.tools as nt
10
11 from ..validator import isvalid, validate, ValidationError
12 from ..nbjson import reads
13 from ..compose import (
14 new_code_cell, new_heading_cell, new_markdown_cell, new_notebook,
15 new_output, new_raw_cell,
16 )
17
18 def test_valid_code_cell():
19 cell = new_code_cell()
20 validate(cell, 'code_cell')
21
22 def test_invalid_code_cell():
23 cell = new_code_cell()
24
25 cell['source'] = 5
26 with nt.assert_raises(ValidationError):
27 validate(cell, 'code_cell')
28
29 cell = new_code_cell()
30 del cell['metadata']
31
32 with nt.assert_raises(ValidationError):
33 validate(cell, 'code_cell')
34
35 cell = new_code_cell()
36 del cell['source']
37
38 with nt.assert_raises(ValidationError):
39 validate(cell, 'code_cell')
40
41 cell = new_code_cell()
42 del cell['cell_type']
43
44 with nt.assert_raises(ValidationError):
45 validate(cell, 'code_cell')
46
47 def test_invalid_markdown_cell():
48 cell = new_markdown_cell()
49
50 cell['source'] = 5
51 with nt.assert_raises(ValidationError):
52 validate(cell, 'markdown_cell')
53
54 cell = new_markdown_cell()
55 del cell['metadata']
56
57 with nt.assert_raises(ValidationError):
58 validate(cell, 'markdown_cell')
59
60 cell = new_markdown_cell()
61 del cell['source']
62
63 with nt.assert_raises(ValidationError):
64 validate(cell, 'markdown_cell')
65
66 cell = new_markdown_cell()
67 del cell['cell_type']
68
69 with nt.assert_raises(ValidationError):
70 validate(cell, 'markdown_cell')
71
72 def test_invalid_heading_cell():
73 cell = new_heading_cell()
74
75 cell['source'] = 5
76 with nt.assert_raises(ValidationError):
77 validate(cell, 'heading_cell')
78
79 cell = new_heading_cell()
80 del cell['metadata']
81
82 with nt.assert_raises(ValidationError):
83 validate(cell, 'heading_cell')
84
85 cell = new_heading_cell()
86 del cell['source']
87
88 with nt.assert_raises(ValidationError):
89 validate(cell, 'heading_cell')
90
91 cell = new_heading_cell()
92 del cell['cell_type']
93
94 with nt.assert_raises(ValidationError):
95 validate(cell, 'heading_cell')
96
97 def test_invalid_raw_cell():
98 cell = new_raw_cell()
99
100 cell['source'] = 5
101 with nt.assert_raises(ValidationError):
102 validate(cell, 'raw_cell')
103
104 cell = new_raw_cell()
105 del cell['metadata']
106
107 with nt.assert_raises(ValidationError):
108 validate(cell, 'raw_cell')
109
110 cell = new_raw_cell()
111 del cell['source']
112
113 with nt.assert_raises(ValidationError):
114 validate(cell, 'raw_cell')
115
116 cell = new_raw_cell()
117 del cell['cell_type']
118
119 with nt.assert_raises(ValidationError):
120 validate(cell, 'raw_cell')
121
122 def test_sample_notebook():
123 here = os.path.dirname(__file__)
124 with io.open(os.path.join(here, "v4-test.ipynb"), encoding='utf-8') as f:
125 nb = reads(f.read())
126 validate(nb)
@@ -0,0 +1,155 b''
1 {
2 "metadata": {
3 "cell_tags": ["<None>", null],
4 "name": "",
5 "kernel_info": {
6 "name": "python",
7 "language": "python"
8 }
9 },
10 "nbformat": 4,
11 "nbformat_minor": 0,
12 "cells": [
13 {
14 "cell_type": "heading",
15 "level": 1,
16 "metadata": {},
17 "source": [
18 "nbconvert latex test"
19 ]
20 },
21 {
22 "cell_type": "markdown",
23 "metadata": {},
24 "source": [
25 "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
26 ]
27 },
28 {
29 "cell_type": "heading",
30 "level": 2,
31 "metadata": {},
32 "source": [
33 "Printed Using Python"
34 ]
35 },
36 {
37 "cell_type": "code",
38 "source": [
39 "print(\"hello\")"
40 ],
41 "metadata": {
42 "collapsed": false,
43 "autoscroll": false
44 },
45 "outputs": [
46 {
47 "output_type": "stream",
48 "metadata": {},
49 "stream": "stdout",
50 "text": [
51 "hello\n"
52 ]
53 }
54 ],
55 "prompt_number": 1
56 },
57 {
58 "cell_type": "heading",
59 "level": 2,
60 "metadata": {},
61 "source": [
62 "Pyout"
63 ]
64 },
65 {
66 "cell_type": "code",
67 "source": [
68 "from IPython.display import HTML\n",
69 "HTML(\"\"\"\n",
70 "<script>\n",
71 "console.log(\"hello\");\n",
72 "</script>\n",
73 "<b>HTML</b>\n",
74 "\"\"\")"
75 ],
76 "metadata": {
77 "collapsed": false,
78 "autoscroll": false
79 },
80 "outputs": [
81 {
82 "text/html": [
83 "\n",
84 "<script>\n",
85 "console.log(\"hello\");\n",
86 "</script>\n",
87 "<b>HTML</b>\n"
88 ],
89 "metadata": {},
90 "output_type": "execute_result",
91 "prompt_number": 3,
92 "text/plain": [
93 "<IPython.core.display.HTML at 0x1112757d0>"
94 ]
95 }
96 ],
97 "prompt_number": 3
98 },
99 {
100 "cell_type": "code",
101 "source": [
102 "%%javascript\n",
103 "console.log(\"hi\");"
104 ],
105 "metadata": {
106 "collapsed": false,
107 "autoscroll": false
108 },
109 "outputs": [
110 {
111 "text/javascript": [
112 "console.log(\"hi\");"
113 ],
114 "metadata": {},
115 "output_type": "display_data",
116 "text/plain": [
117 "<IPython.core.display.Javascript at 0x1112b4b50>"
118 ]
119 }
120 ],
121 "prompt_number": 7
122 },
123 {
124 "cell_type": "heading",
125 "level": 3,
126 "metadata": {},
127 "source": [
128 "Image"
129 ]
130 },
131 {
132 "cell_type": "code",
133 "source": [
134 "from IPython.display import Image\n",
135 "Image(\"http://ipython.org/_static/IPy_header.png\")"
136 ],
137 "metadata": {
138 "collapsed": false,
139 "autoscroll": false
140 },
141 "outputs": [
142 {
143 "metadata": {},
144 "output_type": "execute_result",
145 "image/png": "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\n",
146 "prompt_number": 6,
147 "text/plain": [
148 "<IPython.core.display.Image at 0x111275490>"
149 ]
150 }
151 ],
152 "prompt_number": 6
153 }
154 ]
155 }
@@ -1,74 +1,22 b''
1 """The main API for the v3 notebook format.
1 """The main API for the v4 notebook format."""
2
2
3 Authors:
3 # Copyright (c) IPython Development Team.
4
4 # Distributed under the terms of the Modified BSD License.
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
5
19 from .nbbase import (
6 from .nbbase import (
20 NotebookNode,
7 NotebookNode,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
8 nbformat, nbformat_minor, nbformat_schema,
22 new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor,
9 )
23 nbformat_schema
10
11 from .compose import (
12 new_code_cell, new_heading_cell, new_markdown_cell, new_notebook,
13 new_output,
24 )
14 )
25
15
26 from .nbjson import reads as reads_json, writes as writes_json
16 from .nbjson import reads as reads_json, writes as writes_json
27 from .nbjson import reads as read_json, writes as write_json
17 from .nbjson import reads as read_json, writes as write_json
28 from .nbjson import to_notebook as to_notebook_json
18 from .nbjson import to_notebook as to_notebook_json
29
19
30 from .nbpy import reads as reads_py, writes as writes_py
31 from .nbpy import reads as read_py, writes as write_py
32 from .nbpy import to_notebook as to_notebook_py
33
34 from .convert import downgrade, upgrade
20 from .convert import downgrade, upgrade
35
21
36 #-----------------------------------------------------------------------------
37 # Code
38 #-----------------------------------------------------------------------------
39
40 def parse_filename(fname):
41 """Parse a notebook filename.
42
43 This function takes a notebook filename and returns the notebook
44 format (json/py) and the notebook name. This logic can be
45 summarized as follows:
46
47 * notebook.ipynb -> (notebook.ipynb, notebook, json)
48 * notebook.json -> (notebook.json, notebook, json)
49 * notebook.py -> (notebook.py, notebook, py)
50 * notebook -> (notebook.ipynb, notebook, json)
51
52 Parameters
53 ----------
54 fname : unicode
55 The notebook filename. The filename can use a specific filename
56 extention (.ipynb, .json, .py) or none, in which case .ipynb will
57 be assumed.
58
22
59 Returns
60 -------
61 (fname, name, format) : (unicode, unicode, unicode)
62 The filename, notebook name and format.
63 """
64 if fname.endswith(u'.ipynb'):
65 format = u'json'
66 elif fname.endswith(u'.json'):
67 format = u'json'
68 elif fname.endswith(u'.py'):
69 format = u'py'
70 else:
71 fname = fname + u'.ipynb'
72 format = u'json'
73 name = fname.split('.')[0]
74 return fname, name, format
@@ -1,36 +1,20 b''
1 """Code for converting notebooks to and from the v2 format.
1 """Code for converting notebooks to and from v3."""
2
2
3 Authors:
3 # Copyright (c) IPython Development Team.
4
4 # Distributed under the terms of the Modified BSD License.
5 * Brian Granger
6 * Min RK
7 * Jonathan Frederic
8 """
9
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2011 The IPython Development Team
12 #
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
16
17 #-----------------------------------------------------------------------------
18 # Imports
19 #-----------------------------------------------------------------------------
20
5
21 from .nbbase import (
6 from .nbbase import (
22 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
7 nbformat, nbformat_minor,
23 nbformat, nbformat_minor
24 )
8 )
25
9
26 from IPython.nbformat import v2
10 from IPython.nbformat import v3
27
11
28 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
29 # Code
13 # Code
30 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
31
15
32 def upgrade(nb, from_version=2, from_minor=0):
16 def upgrade(nb, from_version=3, from_minor=0):
33 """Convert a notebook to v3.
17 """Convert a notebook to v4.
34
18
35 Parameters
19 Parameters
36 ----------
20 ----------
@@ -41,50 +25,135 b' def upgrade(nb, from_version=2, from_minor=0):'
41 from_minor : int
25 from_minor : int
42 The original minor version of the notebook to convert (only relevant for v >= 3).
26 The original minor version of the notebook to convert (only relevant for v >= 3).
43 """
27 """
44 if from_version == 2:
28 if from_version == 3:
45 # Mark the original nbformat so consumers know it has been converted.
29 # Mark the original nbformat so consumers know it has been converted.
46 nb.nbformat = nbformat
30 nb.nbformat = nbformat
47 nb.nbformat_minor = nbformat_minor
31 nb.nbformat_minor = nbformat_minor
48
32
49 nb.orig_nbformat = 2
33 nb.orig_nbformat = 3
34 # remove worksheet(s)
35 nb['cells'] = cells = []
36 # In the unlikely event of multiple worksheets,
37 # they will be flattened
38 for ws in nb.pop('worksheets', []):
39 # upgrade each cell
40 for cell in ws['cells']:
41 cells.append(upgrade_cell(cell))
42 # upgrade metadata?
43 nb.metadata.pop('name', '')
50 return nb
44 return nb
51 elif from_version == 3:
45 elif from_version == 4:
46 # nothing to do
52 if from_minor != nbformat_minor:
47 if from_minor != nbformat_minor:
53 nb.orig_nbformat_minor = from_minor
48 nb.orig_nbformat_minor = from_minor
54 nb.nbformat_minor = nbformat_minor
49 nb.nbformat_minor = nbformat_minor
55 return nb
50 return nb
56 else:
51 else:
57 raise ValueError('Cannot convert a notebook directly from v%s to v3. ' \
52 raise ValueError('Cannot convert a notebook directly from v%s to v4. ' \
58 'Try using the IPython.nbformat.convert module.' % from_version)
53 'Try using the IPython.nbformat.convert module.' % from_version)
59
54
55 def upgrade_cell(cell):
56 """upgrade a cell from v3 to v4
60
57
61 def heading_to_md(cell):
58 code cell:
62 """turn heading cell into corresponding markdown"""
59 - remove language metadata
63 cell.cell_type = "markdown"
60 - cell.input -> cell.source
64 level = cell.pop('level', 1)
61 - update outputs
65 cell.source = '#'*level + ' ' + cell.source
62 """
66
63 if cell.cell_type == 'code':
67
64 cell.metadata.pop('language', '')
68 def raw_to_md(cell):
65 cell.source = cell.pop('input')
69 """let raw passthrough as markdown"""
66 cell.outputs = upgrade_outputs(cell)
70 cell.cell_type = "markdown"
67 return cell
71
68
69 def downgrade_cell(cell):
70 if cell.cell_type == 'code':
71 cell.input = cell.pop('source')
72 cell.outputs = downgrade_outputs(cell)
73 return cell
74
75 _mime_map = {
76 "text" : "text/plain",
77 "html" : "text/html",
78 "svg" : "image/svg+xml",
79 "png" : "image/png",
80 "jpeg" : "image/jpeg",
81 "latex" : "text/latex",
82 "json" : "application/json",
83 "javascript" : "application/javascript",
84 };
85
86 def to_mime_key(d):
87 """convert dict with v3 aliases to plain mime-type keys"""
88 for alias, mime in _mime_map.items():
89 if alias in d:
90 d[mime] = d.pop(alias)
91 return d
92
93 def from_mime_key(d):
94 """convert dict with mime-type keys to v3 aliases"""
95 for alias, mime in _mime_map.items():
96 if mime in d:
97 d[alias] = d.pop(mime)
98 return d
99
100 def upgrade_output(output):
101 """upgrade a single code cell output from v3 to v4
102
103 - pyout -> execute_result
104 - pyerr -> error
105 - mime-type keys
106 """
107 if output['output_type'] == 'pyout':
108 output['output_type'] = 'execute_result'
109 to_mime_key(output)
110 to_mime_key(output.get('metadata', {}))
111 elif output['output_type'] == 'pyerr':
112 output['output_type'] = 'error'
113 elif output['output_type'] == 'display_data':
114 to_mime_key(output)
115 to_mime_key(output.get('metadata', {}))
116 return output
117
118 def downgrade_output(output):
119 """downgrade a single code cell output to v3 from v4
120
121 - pyout <- execute_result
122 - pyerr <- error
123 - un-mime-type keys
124 """
125 if output['output_type'] == 'execute_result':
126 output['output_type'] = 'pyout'
127 from_mime_key(output)
128 from_mime_key(output.get('metadata', {}))
129 elif output['output_type'] == 'error':
130 output['output_type'] = 'pyerr'
131 elif output['output_type'] == 'display_data':
132 from_mime_key(output)
133 from_mime_key(output.get('metadata', {}))
134 return output
135
136 def upgrade_outputs(outputs):
137 """upgrade outputs of a code cell from v3 to v4"""
138 return [upgrade_output(op) for op in outputs]
139
140 def downgrade_outputs(outputs):
141 """downgrade outputs of a code cell to v3 from v4"""
142 return [downgrade_output(op) for op in outputs]
72
143
73 def downgrade(nb):
144 def downgrade(nb):
74 """Convert a v3 notebook to v2.
145 """Convert a v4 notebook to v3.
75
146
76 Parameters
147 Parameters
77 ----------
148 ----------
78 nb : NotebookNode
149 nb : NotebookNode
79 The Python representation of the notebook to convert.
150 The Python representation of the notebook to convert.
80 """
151 """
81 if nb.nbformat != 3:
152 if nb.nbformat != 4:
82 return nb
153 return nb
83 nb.nbformat = 2
154 nb.nbformat = v3.nbformat
84 for ws in nb.worksheets:
155 nb.nbformat_minor = v3.nbformat_minor
85 for cell in ws.cells:
156 cells = [ downgrade_cell(cell) for cell in nb.cells ]
86 if cell.cell_type == 'heading':
157 nb.worksheets = [v3.new_worksheet(cells=cells)]
87 heading_to_md(cell)
158 nb.metadata.setdefault('name', '')
88 elif cell.cell_type == 'raw':
89 raw_to_md(cell)
90 return nb No newline at end of file
159 return nb
@@ -15,14 +15,11 b' import uuid'
15 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
16 from IPython.utils.py3compat import cast_unicode, unicode_type
16 from IPython.utils.py3compat import cast_unicode, unicode_type
17
17
18 #-----------------------------------------------------------------------------
19 # Code
20 #-----------------------------------------------------------------------------
21
18
22 # Change this when incrementing the nbformat version
19 # Change this when incrementing the nbformat version
23 nbformat = 3
20 nbformat = 4
24 nbformat_minor = 0
21 nbformat_minor = 0
25 nbformat_schema = 'v3.withref.json'
22 nbformat_schema = 'v4.withref.json'
26
23
27 class NotebookNode(Struct):
24 class NotebookNode(Struct):
28 pass
25 pass
@@ -39,166 +36,3 b' def from_dict(d):'
39 else:
36 else:
40 return d
37 return d
41
38
42
43 def new_output(output_type, output_text=None, output_png=None,
44 output_html=None, output_svg=None, output_latex=None, output_json=None,
45 output_javascript=None, output_jpeg=None, prompt_number=None,
46 ename=None, evalue=None, traceback=None, stream=None, metadata=None):
47 """Create a new output, to go in the ``cell.outputs`` list of a code cell.
48 """
49 output = NotebookNode()
50 output.output_type = unicode_type(output_type)
51
52 if metadata is None:
53 metadata = {}
54 if not isinstance(metadata, dict):
55 raise TypeError("metadata must be dict")
56 output.metadata = metadata
57
58 if output_type != 'pyerr':
59 if output_text is not None:
60 output.text = cast_unicode(output_text)
61 if output_png is not None:
62 output.png = cast_unicode(output_png)
63 if output_jpeg is not None:
64 output.jpeg = cast_unicode(output_jpeg)
65 if output_html is not None:
66 output.html = cast_unicode(output_html)
67 if output_svg is not None:
68 output.svg = cast_unicode(output_svg)
69 if output_latex is not None:
70 output.latex = cast_unicode(output_latex)
71 if output_json is not None:
72 output.json = cast_unicode(output_json)
73 if output_javascript is not None:
74 output.javascript = cast_unicode(output_javascript)
75
76 if output_type == u'pyout':
77 if prompt_number is not None:
78 output.prompt_number = int(prompt_number)
79
80 if output_type == u'pyerr':
81 if ename is not None:
82 output.ename = cast_unicode(ename)
83 if evalue is not None:
84 output.evalue = cast_unicode(evalue)
85 if traceback is not None:
86 output.traceback = [cast_unicode(frame) for frame in list(traceback)]
87
88 if output_type == u'stream':
89 output.stream = 'stdout' if stream is None else cast_unicode(stream)
90
91 return output
92
93
94 def new_code_cell(input=None, prompt_number=None, outputs=None,
95 language=u'python', collapsed=False, metadata=None):
96 """Create a new code cell with input and output"""
97 cell = NotebookNode()
98 cell.cell_type = u'code'
99 if language is not None:
100 cell.language = cast_unicode(language)
101 if input is not None:
102 cell.input = cast_unicode(input)
103 if prompt_number is not None:
104 cell.prompt_number = int(prompt_number)
105 if outputs is None:
106 cell.outputs = []
107 else:
108 cell.outputs = outputs
109 if collapsed is not None:
110 cell.collapsed = bool(collapsed)
111 cell.metadata = NotebookNode(metadata or {})
112
113 return cell
114
115 def new_text_cell(cell_type, source=None, rendered=None, metadata=None):
116 """Create a new text cell."""
117 cell = NotebookNode()
118 # VERSIONHACK: plaintext -> raw
119 # handle never-released plaintext name for raw cells
120 if cell_type == 'plaintext':
121 cell_type = 'raw'
122 if source is not None:
123 cell.source = cast_unicode(source)
124 if rendered is not None:
125 cell.rendered = cast_unicode(rendered)
126 cell.metadata = NotebookNode(metadata or {})
127 cell.cell_type = cell_type
128 return cell
129
130
131 def new_heading_cell(source=None, rendered=None, level=1, metadata=None):
132 """Create a new section cell with a given integer level."""
133 cell = NotebookNode()
134 cell.cell_type = u'heading'
135 if source is not None:
136 cell.source = cast_unicode(source)
137 if rendered is not None:
138 cell.rendered = cast_unicode(rendered)
139 cell.level = int(level)
140 cell.metadata = NotebookNode(metadata or {})
141 return cell
142
143
144 def new_worksheet(name=None, cells=None, metadata=None):
145 """Create a worksheet by name with with a list of cells."""
146 ws = NotebookNode()
147 if name is not None:
148 ws.name = cast_unicode(name)
149 if cells is None:
150 ws.cells = []
151 else:
152 ws.cells = list(cells)
153 ws.metadata = NotebookNode(metadata or {})
154 return ws
155
156
157 def new_notebook(name=None, metadata=None, worksheets=None):
158 """Create a notebook by name, id and a list of worksheets."""
159 nb = NotebookNode()
160 nb.nbformat = nbformat
161 nb.nbformat_minor = nbformat_minor
162 if worksheets is None:
163 nb.worksheets = []
164 else:
165 nb.worksheets = list(worksheets)
166 if metadata is None:
167 nb.metadata = new_metadata()
168 else:
169 nb.metadata = NotebookNode(metadata)
170 if name is not None:
171 nb.metadata.name = cast_unicode(name)
172 return nb
173
174
175 def new_metadata(name=None, authors=None, license=None, created=None,
176 modified=None, gistid=None):
177 """Create a new metadata node."""
178 metadata = NotebookNode()
179 if name is not None:
180 metadata.name = cast_unicode(name)
181 if authors is not None:
182 metadata.authors = list(authors)
183 if created is not None:
184 metadata.created = cast_unicode(created)
185 if modified is not None:
186 metadata.modified = cast_unicode(modified)
187 if license is not None:
188 metadata.license = cast_unicode(license)
189 if gistid is not None:
190 metadata.gistid = cast_unicode(gistid)
191 return metadata
192
193 def new_author(name=None, email=None, affiliation=None, url=None):
194 """Create a new author."""
195 author = NotebookNode()
196 if name is not None:
197 author.name = cast_unicode(name)
198 if email is not None:
199 author.email = cast_unicode(email)
200 if affiliation is not None:
201 author.affiliation = cast_unicode(affiliation)
202 if url is not None:
203 author.url = cast_unicode(url)
204 return author
@@ -1,34 +1,18 b''
1 """Read and write notebooks in JSON format.
1 """Read and write notebooks in JSON format."""
2
2
3 Authors:
3 # Copyright (c) IPython Development Team.
4
4 # Distributed under the terms of the Modified BSD License.
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
5
19 import copy
6 import copy
20 import json
7 import json
21
8
9 from IPython.utils import py3compat
10
22 from .nbbase import from_dict
11 from .nbbase import from_dict
23 from .rwbase import (
12 from .rwbase import (
24 NotebookReader, NotebookWriter, restore_bytes, rejoin_lines, split_lines
13 NotebookReader, NotebookWriter, rejoin_lines, split_lines
25 )
14 )
26
15
27 from IPython.utils import py3compat
28
29 #-----------------------------------------------------------------------------
30 # Code
31 #-----------------------------------------------------------------------------
32
16
33 class BytesEncoder(json.JSONEncoder):
17 class BytesEncoder(json.JSONEncoder):
34 """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""
18 """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""
@@ -1,51 +1,19 b''
1 """Base classes and utilities for readers and writers.
1 """Base classes and utilities for readers and writers."""
2
2
3 Authors:
3 # Copyright (c) IPython Development Team.
4
4 # Distributed under the terms of the Modified BSD License.
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 from base64 import encodestring, decodestring
20 import pprint
21
5
22 from IPython.utils import py3compat
6 from IPython.utils import py3compat
23 from IPython.utils.py3compat import str_to_bytes, unicode_type, string_types
7 from IPython.utils.py3compat import unicode_type, string_types
24
25 #-----------------------------------------------------------------------------
26 # Code
27 #-----------------------------------------------------------------------------
28
29 def restore_bytes(nb):
30 """Restore bytes of image data from unicode-only formats.
31
32 Base64 encoding is handled elsewhere. Bytes objects in the notebook are
33 always b64-encoded. We DO NOT encode/decode around file formats.
34
35 Note: this is never used
36 """
37 for ws in nb.worksheets:
38 for cell in ws.cells:
39 if cell.cell_type == 'code':
40 for output in cell.outputs:
41 if 'png' in output:
42 output.png = str_to_bytes(output.png, 'ascii')
43 if 'jpeg' in output:
44 output.jpeg = str_to_bytes(output.jpeg, 'ascii')
45 return nb
46
8
47 # output keys that are likely to have multiline values
9 # output keys that are likely to have multiline values
48 _multiline_outputs = ['text', 'html', 'svg', 'latex', 'javascript', 'json']
10 _multiline_outputs = {
11 'text/plain',
12 'text/html',
13 'image/svg+xml',
14 'text/latex',
15 'application/javascript',
16 }
49
17
50
18
51 # FIXME: workaround for old splitlines()
19 # FIXME: workaround for old splitlines()
@@ -73,21 +41,15 b' def rejoin_lines(nb):'
73
41
74 Used when reading JSON files that may have been passed through split_lines.
42 Used when reading JSON files that may have been passed through split_lines.
75 """
43 """
76 for ws in nb.worksheets:
44 for cell in nb.cells:
77 for cell in ws.cells:
45 if 'source' in cell and isinstance(cell.source, list):
78 if cell.cell_type == 'code':
46 cell.source = _join_lines(cell.source)
79 if 'input' in cell and isinstance(cell.input, list):
47 if cell.cell_type == 'code':
80 cell.input = _join_lines(cell.input)
48 for output in cell.outputs:
81 for output in cell.outputs:
49 for key in _multiline_outputs:
82 for key in _multiline_outputs:
50 item = output.get(key, None)
83 item = output.get(key, None)
84 if isinstance(item, list):
85 output[key] = _join_lines(item)
86 else: # text, heading cell
87 for key in ['source', 'rendered']:
88 item = cell.get(key, None)
89 if isinstance(item, list):
51 if isinstance(item, list):
90 cell[key] = _join_lines(item)
52 output[key] = _join_lines(item)
91 return nb
53 return nb
92
54
93
55
@@ -99,61 +61,17 b' def split_lines(nb):'
99
61
100 Used when writing JSON files.
62 Used when writing JSON files.
101 """
63 """
102 for ws in nb.worksheets:
64 for cell in nb.cells:
103 for cell in ws.cells:
65 source = cell.get('source', None)
104 if cell.cell_type == 'code':
66 if isinstance(source, string_types):
105 if 'input' in cell and isinstance(cell.input, string_types):
67 cell['source'] = source.splitlines(True)
106 cell.input = cell.input.splitlines(True)
68
107 for output in cell.outputs:
69 if cell.cell_type == 'code':
108 for key in _multiline_outputs:
70 for output in cell.outputs:
109 item = output.get(key, None)
71 for key in _multiline_outputs:
110 if isinstance(item, string_types):
72 item = output.get(key, None)
111 output[key] = item.splitlines(True)
112 else: # text, heading cell
113 for key in ['source', 'rendered']:
114 item = cell.get(key, None)
115 if isinstance(item, string_types):
73 if isinstance(item, string_types):
116 cell[key] = item.splitlines(True)
74 output[key] = item.splitlines(True)
117 return nb
118
119 # b64 encode/decode are never actually used, because all bytes objects in
120 # the notebook are already b64-encoded, and we don't need/want to double-encode
121
122 def base64_decode(nb):
123 """Restore all bytes objects in the notebook from base64-encoded strings.
124
125 Note: This is never used
126 """
127 for ws in nb.worksheets:
128 for cell in ws.cells:
129 if cell.cell_type == 'code':
130 for output in cell.outputs:
131 if 'png' in output:
132 if isinstance(output.png, unicode_type):
133 output.png = output.png.encode('ascii')
134 output.png = decodestring(output.png)
135 if 'jpeg' in output:
136 if isinstance(output.jpeg, unicode_type):
137 output.jpeg = output.jpeg.encode('ascii')
138 output.jpeg = decodestring(output.jpeg)
139 return nb
140
141
142 def base64_encode(nb):
143 """Base64 encode all bytes objects in the notebook.
144
145 These will be b64-encoded unicode strings
146
147 Note: This is never used
148 """
149 for ws in nb.worksheets:
150 for cell in ws.cells:
151 if cell.cell_type == 'code':
152 for output in cell.outputs:
153 if 'png' in output:
154 output.png = encodestring(output.png).decode('ascii')
155 if 'jpeg' in output:
156 output.jpeg = encodestring(output.jpeg).decode('ascii')
157 return nb
75 return nb
158
76
159
77
@@ -6,13 +6,7 b' import tempfile'
6
6
7 pjoin = os.path.join
7 pjoin = os.path.join
8
8
9 from ..nbbase import (
9 from .nbexamples import nb0
10 NotebookNode,
11 new_code_cell, new_text_cell, new_worksheet, new_notebook
12 )
13
14 from ..nbpy import reads, writes, read, write
15 from .nbexamples import nb0, nb0_py
16
10
17
11
18 def open_utf8(fname, mode):
12 def open_utf8(fname, mode):
@@ -3,150 +3,103 b''
3 import os
3 import os
4 from base64 import encodestring
4 from base64 import encodestring
5
5
6 from ..nbbase import (
6 from ..compose import (
7 NotebookNode,
7 new_code_cell, new_heading_cell, new_markdown_cell, new_notebook,
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
8 new_output, new_raw_cell
9 new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor
10 )
9 )
11
10
12 # some random base64-encoded *text*
11 # some random base64-encoded *text*
13 png = encodestring(os.urandom(5)).decode('ascii')
12 png = encodestring(os.urandom(5)).decode('ascii')
14 jpeg = encodestring(os.urandom(6)).decode('ascii')
13 jpeg = encodestring(os.urandom(6)).decode('ascii')
15
14
16 ws = new_worksheet(name='worksheet1')
15 cells = []
17
16 cells.append(new_markdown_cell(
18 ws.cells.append(new_text_cell(
19 u'html',
20 source='Some NumPy Examples',
17 source='Some NumPy Examples',
21 rendered='Some NumPy Examples'
22 ))
18 ))
23
19
24
20
25 ws.cells.append(new_code_cell(
21 cells.append(new_code_cell(
26 input='import numpy',
22 source='import numpy',
27 prompt_number=1,
23 prompt_number=1,
28 collapsed=False
29 ))
24 ))
30
25
31 ws.cells.append(new_text_cell(
26 cells.append(new_markdown_cell(
32 u'markdown',
33 source='A random array',
27 source='A random array',
34 rendered='A random array'
35 ))
28 ))
36
29
37 ws.cells.append(new_text_cell(
30 cells.append(new_raw_cell(
38 u'raw',
39 source='A random array',
31 source='A random array',
40 ))
32 ))
41
33
42 ws.cells.append(new_heading_cell(
34 cells.append(new_heading_cell(
43 u'My Heading',
35 source=u'My Heading',
44 level=2
36 level=2,
45 ))
37 ))
46
38
47 ws.cells.append(new_code_cell(
39 cells.append(new_code_cell(
48 input='a = numpy.random.rand(100)',
40 source='a = numpy.random.rand(100)',
49 prompt_number=2,
41 prompt_number=2,
50 collapsed=True
51 ))
42 ))
52 ws.cells.append(new_code_cell(
43 cells.append(new_code_cell(
53 input='a = 10\nb = 5\n',
44 source='a = 10\nb = 5\n',
54 prompt_number=3,
45 prompt_number=3,
55 ))
46 ))
56 ws.cells.append(new_code_cell(
47 cells.append(new_code_cell(
57 input='a = 10\nb = 5',
48 source='a = 10\nb = 5',
58 prompt_number=4,
49 prompt_number=4,
59 ))
50 ))
60
51
61 ws.cells.append(new_code_cell(
52 cells.append(new_code_cell(
62 input=u'print "ünîcødé"',
53 source=u'print "ünîcødé"',
63 prompt_number=3,
54 prompt_number=3,
64 collapsed=False,
65 outputs=[new_output(
55 outputs=[new_output(
66 output_type=u'pyout',
56 output_type=u'execute_result',
67 output_text=u'<array a>',
57 mime_bundle={
68 output_html=u'The HTML rep',
58 'text/plain': u'<array a>',
69 output_latex=u'$a$',
59 'text/html': u'The HTML rep',
70 output_png=png,
60 'text/latex': u'$a$',
71 output_jpeg=jpeg,
61 'image/png': png,
72 output_svg=u'<svg>',
62 'image/jpeg': jpeg,
73 output_json=u'json data',
63 'image/svg+xml': u'<svg>',
74 output_javascript=u'var i=0;',
64 'application/json': {
65 'key': 'value'
66 },
67 'application/javascript': u'var i=0;'
68 },
75 prompt_number=3
69 prompt_number=3
76 ),new_output(
70 ),new_output(
77 output_type=u'display_data',
71 output_type=u'display_data',
78 output_text=u'<array a>',
72 mime_bundle={
79 output_html=u'The HTML rep',
73 'text/plain': u'<array a>',
80 output_latex=u'$a$',
74 'text/html': u'The HTML rep',
81 output_png=png,
75 'text/latex': u'$a$',
82 output_jpeg=jpeg,
76 'image/png': png,
83 output_svg=u'<svg>',
77 'image/jpeg': jpeg,
84 output_json=u'json data',
78 'image/svg+xml': u'<svg>',
85 output_javascript=u'var i=0;'
79 'application/json': {
80 'key': 'value'
81 },
82 'application/javascript': u'var i=0;'
83 },
86 ),new_output(
84 ),new_output(
87 output_type=u'pyerr',
85 output_type=u'error',
88 ename=u'NameError',
86 ename=u'NameError',
89 evalue=u'NameError was here',
87 evalue=u'NameError was here',
90 traceback=[u'frame 0', u'frame 1', u'frame 2']
88 traceback=[u'frame 0', u'frame 1', u'frame 2']
91 ),new_output(
89 ),new_output(
92 output_type=u'stream',
90 output_type=u'stream',
93 output_text='foo\rbar\r\n'
91 text='foo\rbar\r\n'
94 ),new_output(
92 ),new_output(
95 output_type=u'stream',
93 output_type=u'stream',
96 stream='stderr',
94 stream='stderr',
97 output_text='\rfoo\rbar\n'
95 text='\rfoo\rbar\n'
98 )]
96 )]
99 ))
97 ))
100
98
101 authors = [new_author(name='Bart Simpson',email='bsimpson@fox.com',
99 nb0 = new_notebook(cells=cells,
102 affiliation=u'Fox',url=u'http://www.fox.com')]
100 metadata={
103 md = new_metadata(name=u'My Notebook',license=u'BSD',created=u'8601_goes_here',
101 'language': 'python',
104 modified=u'8601_goes_here',gistid=u'21341231',authors=authors)
102 }
105
106 nb0 = new_notebook(
107 worksheets=[ws, new_worksheet(name='worksheet2')],
108 metadata=md
109 )
103 )
110
104
111 nb0_py = u"""# -*- coding: utf-8 -*-
112 # <nbformat>%i.%i</nbformat>
113
114 # <htmlcell>
115
116 # Some NumPy Examples
117
118 # <codecell>
119
120 import numpy
121
122 # <markdowncell>
123
124 # A random array
125
126 # <rawcell>
127
128 # A random array
129
130 # <headingcell level=2>
131
132 # My Heading
133
134 # <codecell>
135
136 a = numpy.random.rand(100)
137
138 # <codecell>
139
140 a = 10
141 b = 5
142
143 # <codecell>
144
145 a = 10
146 b = 5
147
148 # <codecell>
149
150 print "ünîcødé"
151
105
152 """ % (nbformat, nbformat_minor)
@@ -1,4 +1,3 b''
1 import pprint
2 from base64 import decodestring
1 from base64 import decodestring
3 from unittest import TestCase
2 from unittest import TestCase
4
3
@@ -9,8 +8,6 b' from .nbexamples import nb0'
9
8
10 from . import formattest
9 from . import formattest
11
10
12 from .nbexamples import nb0
13
14
11
15 class TestJSON(formattest.NBFormatTest, TestCase):
12 class TestJSON(formattest.NBFormatTest, TestCase):
16
13
@@ -36,13 +33,13 b' class TestJSON(formattest.NBFormatTest, TestCase):'
36 s = writes(nb0)
33 s = writes(nb0)
37 nb1 = nbjson.reads(s)
34 nb1 = nbjson.reads(s)
38 found_png = False
35 found_png = False
39 for cell in nb1.worksheets[0].cells:
36 for cell in nb1.cells:
40 if not 'outputs' in cell:
37 if not 'outputs' in cell:
41 continue
38 continue
42 for output in cell.outputs:
39 for output in cell.outputs:
43 if 'png' in output:
40 if 'image/png' in output:
44 found_png = True
41 found_png = True
45 pngdata = output['png']
42 pngdata = output['image/png']
46 self.assertEqual(type(pngdata), unicode_type)
43 self.assertEqual(type(pngdata), unicode_type)
47 # test that it is valid b64 data
44 # test that it is valid b64 data
48 b64bytes = pngdata.encode('ascii')
45 b64bytes = pngdata.encode('ascii')
@@ -54,13 +51,13 b' class TestJSON(formattest.NBFormatTest, TestCase):'
54 s = writes(nb0)
51 s = writes(nb0)
55 nb1 = nbjson.reads(s)
52 nb1 = nbjson.reads(s)
56 found_jpeg = False
53 found_jpeg = False
57 for cell in nb1.worksheets[0].cells:
54 for cell in nb1.cells:
58 if not 'outputs' in cell:
55 if not 'outputs' in cell:
59 continue
56 continue
60 for output in cell.outputs:
57 for output in cell.outputs:
61 if 'jpeg' in output:
58 if 'image/jpeg' in output:
62 found_jpeg = True
59 found_jpeg = True
63 jpegdata = output['jpeg']
60 jpegdata = output['image/jpeg']
64 self.assertEqual(type(jpegdata), unicode_type)
61 self.assertEqual(type(jpegdata), unicode_type)
65 # test that it is valid b64 data
62 # test that it is valid b64 data
66 b64bytes = jpegdata.encode('ascii')
63 b64bytes = jpegdata.encode('ascii')
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now