Show More
@@ -36,7 +36,7 b' class PreprocessorTestsBase(TestsBase):' | |||||
36 | nbformat.new_output(output_type="stream", stream="stdout", output_text="d"), |
|
36 | nbformat.new_output(output_type="stream", stream="stdout", output_text="d"), | |
37 | nbformat.new_output(output_type="stream", stream="stderr", output_text="e"), |
|
37 | nbformat.new_output(output_type="stream", stream="stderr", output_text="e"), | |
38 | nbformat.new_output(output_type="stream", stream="stderr", output_text="f"), |
|
38 | nbformat.new_output(output_type="stream", stream="stderr", output_text="f"), | |
39 |
nbformat.new_output(output_type="png", output_png= |
|
39 | nbformat.new_output(output_type="png", output_png='Zw==')] #g | |
40 |
|
40 | |||
41 | cells=[nbformat.new_code_cell(input="$ e $", prompt_number=1,outputs=outputs), |
|
41 | cells=[nbformat.new_code_cell(input="$ e $", prompt_number=1,outputs=outputs), | |
42 | nbformat.new_text_cell('markdown', source="$ e $")] |
|
42 | nbformat.new_text_cell('markdown', source="$ e $")] |
@@ -46,12 +46,14 b' class TestExtractOutput(PreprocessorTestsBase):' | |||||
46 | nb, res = preprocessor(nb, res) |
|
46 | nb, res = preprocessor(nb, res) | |
47 |
|
47 | |||
48 | # Check if text was extracted. |
|
48 | # Check if text was extracted. | |
49 |
|
|
49 | output = nb.worksheets[0].cells[0].outputs[1] | |
50 | text_filename = nb.worksheets[0].cells[0].outputs[1]['text_filename'] |
|
50 | assert 'text_filename' in output | |
|
51 | text_filename = output['text_filename'] | |||
51 |
|
52 | |||
52 | # Check if png was extracted. |
|
53 | # Check if png was extracted. | |
53 |
|
|
54 | output = nb.worksheets[0].cells[0].outputs[6] | |
54 | png_filename = nb.worksheets[0].cells[0].outputs[6]['png_filename'] |
|
55 | assert 'png_filename' in output | |
|
56 | png_filename = output['png_filename'] | |||
55 |
|
57 | |||
56 | # Verify text output |
|
58 | # Verify text output | |
57 | assert text_filename in res['outputs'] |
|
59 | assert text_filename in res['outputs'] |
@@ -13,6 +13,7 b'' | |||||
13 |
|
13 | |||
14 | import os |
|
14 | import os | |
15 | import glob |
|
15 | import glob | |
|
16 | import sys | |||
16 |
|
17 | |||
17 | from .base import TestsBase |
|
18 | from .base import TestsBase | |
18 |
|
19 | |||
@@ -104,6 +105,17 b' class TestNbConvertApp(TestsBase):' | |||||
104 |
|
105 | |||
105 |
|
106 | |||
106 | @dec.onlyif_cmds_exist('pandoc') |
|
107 | @dec.onlyif_cmds_exist('pandoc') | |
|
108 | def test_png_base64_html_ok(self): | |||
|
109 | """Is embedded png data well formed in HTML?""" | |||
|
110 | with self.create_temp_cwd(['notebook2.ipynb']): | |||
|
111 | self.call('nbconvert --log-level 0 --to HTML ' | |||
|
112 | 'notebook2.ipynb --template full') | |||
|
113 | assert os.path.isfile('notebook2.html') | |||
|
114 | with open('notebook2.html') as f: | |||
|
115 | assert "data:image/png;base64,b'" not in f.read() | |||
|
116 | ||||
|
117 | ||||
|
118 | @dec.onlyif_cmds_exist('pandoc') | |||
107 | def test_template(self): |
|
119 | def test_template(self): | |
108 | """ |
|
120 | """ | |
109 | Do export templates work? |
|
121 | Do export templates work? |
@@ -25,6 +25,7 b' import pprint' | |||||
25 | import uuid |
|
25 | import uuid | |
26 |
|
26 | |||
27 | from IPython.utils.ipstruct import Struct |
|
27 | from IPython.utils.ipstruct import Struct | |
|
28 | from IPython.utils.py3compat import cast_unicode | |||
28 |
|
29 | |||
29 | #----------------------------------------------------------------------------- |
|
30 | #----------------------------------------------------------------------------- | |
30 | # Code |
|
31 | # Code | |
@@ -67,21 +68,21 b' def new_output(output_type=None, output_text=None, output_png=None,' | |||||
67 |
|
68 | |||
68 | if output_type != 'pyerr': |
|
69 | if output_type != 'pyerr': | |
69 | if output_text is not None: |
|
70 | if output_text is not None: | |
70 | output.text = unicode(output_text) |
|
71 | output.text = cast_unicode(output_text) | |
71 | if output_png is not None: |
|
72 | if output_png is not None: | |
72 |
output.png = |
|
73 | output.png = cast_unicode(output_png) | |
73 | if output_jpeg is not None: |
|
74 | if output_jpeg is not None: | |
74 |
output.jpeg = |
|
75 | output.jpeg = cast_unicode(output_jpeg) | |
75 | if output_html is not None: |
|
76 | if output_html is not None: | |
76 | output.html = unicode(output_html) |
|
77 | output.html = cast_unicode(output_html) | |
77 | if output_svg is not None: |
|
78 | if output_svg is not None: | |
78 | output.svg = unicode(output_svg) |
|
79 | output.svg = cast_unicode(output_svg) | |
79 | if output_latex is not None: |
|
80 | if output_latex is not None: | |
80 | output.latex = unicode(output_latex) |
|
81 | output.latex = cast_unicode(output_latex) | |
81 | if output_json is not None: |
|
82 | if output_json is not None: | |
82 | output.json = unicode(output_json) |
|
83 | output.json = cast_unicode(output_json) | |
83 | if output_javascript is not None: |
|
84 | if output_javascript is not None: | |
84 | output.javascript = unicode(output_javascript) |
|
85 | output.javascript = cast_unicode(output_javascript) | |
85 |
|
86 | |||
86 | if output_type == u'pyout': |
|
87 | if output_type == u'pyout': | |
87 | if prompt_number is not None: |
|
88 | if prompt_number is not None: | |
@@ -89,14 +90,14 b' def new_output(output_type=None, output_text=None, output_png=None,' | |||||
89 |
|
90 | |||
90 | if output_type == u'pyerr': |
|
91 | if output_type == u'pyerr': | |
91 | if ename is not None: |
|
92 | if ename is not None: | |
92 | output.ename = unicode(ename) |
|
93 | output.ename = cast_unicode(ename) | |
93 | if evalue is not None: |
|
94 | if evalue is not None: | |
94 | output.evalue = unicode(evalue) |
|
95 | output.evalue = cast_unicode(evalue) | |
95 | if traceback is not None: |
|
96 | if traceback is not None: | |
96 | output.traceback = [unicode(frame) for frame in list(traceback)] |
|
97 | output.traceback = [cast_unicode(frame) for frame in list(traceback)] | |
97 |
|
98 | |||
98 | if output_type == u'stream': |
|
99 | if output_type == u'stream': | |
99 | output.stream = 'stdout' if stream is None else unicode(stream) |
|
100 | output.stream = 'stdout' if stream is None else cast_unicode(stream) | |
100 |
|
101 | |||
101 | return output |
|
102 | return output | |
102 |
|
103 | |||
@@ -107,9 +108,9 b' def new_code_cell(input=None, prompt_number=None, outputs=None,' | |||||
107 | cell = NotebookNode() |
|
108 | cell = NotebookNode() | |
108 | cell.cell_type = u'code' |
|
109 | cell.cell_type = u'code' | |
109 | if language is not None: |
|
110 | if language is not None: | |
110 | cell.language = unicode(language) |
|
111 | cell.language = cast_unicode(language) | |
111 | if input is not None: |
|
112 | if input is not None: | |
112 | cell.input = unicode(input) |
|
113 | cell.input = cast_unicode(input) | |
113 | if prompt_number is not None: |
|
114 | if prompt_number is not None: | |
114 | cell.prompt_number = int(prompt_number) |
|
115 | cell.prompt_number = int(prompt_number) | |
115 | if outputs is None: |
|
116 | if outputs is None: | |
@@ -130,9 +131,9 b' def new_text_cell(cell_type, source=None, rendered=None, metadata=None):' | |||||
130 | if cell_type == 'plaintext': |
|
131 | if cell_type == 'plaintext': | |
131 | cell_type = 'raw' |
|
132 | cell_type = 'raw' | |
132 | if source is not None: |
|
133 | if source is not None: | |
133 | cell.source = unicode(source) |
|
134 | cell.source = cast_unicode(source) | |
134 | if rendered is not None: |
|
135 | if rendered is not None: | |
135 | cell.rendered = unicode(rendered) |
|
136 | cell.rendered = cast_unicode(rendered) | |
136 | cell.metadata = NotebookNode(metadata or {}) |
|
137 | cell.metadata = NotebookNode(metadata or {}) | |
137 | cell.cell_type = cell_type |
|
138 | cell.cell_type = cell_type | |
138 | return cell |
|
139 | return cell | |
@@ -143,9 +144,9 b' def new_heading_cell(source=None, rendered=None, level=1, metadata=None):' | |||||
143 | cell = NotebookNode() |
|
144 | cell = NotebookNode() | |
144 | cell.cell_type = u'heading' |
|
145 | cell.cell_type = u'heading' | |
145 | if source is not None: |
|
146 | if source is not None: | |
146 | cell.source = unicode(source) |
|
147 | cell.source = cast_unicode(source) | |
147 | if rendered is not None: |
|
148 | if rendered is not None: | |
148 | cell.rendered = unicode(rendered) |
|
149 | cell.rendered = cast_unicode(rendered) | |
149 | cell.level = int(level) |
|
150 | cell.level = int(level) | |
150 | cell.metadata = NotebookNode(metadata or {}) |
|
151 | cell.metadata = NotebookNode(metadata or {}) | |
151 | return cell |
|
152 | return cell | |
@@ -155,7 +156,7 b' def new_worksheet(name=None, cells=None, metadata=None):' | |||||
155 | """Create a worksheet by name with with a list of cells.""" |
|
156 | """Create a worksheet by name with with a list of cells.""" | |
156 | ws = NotebookNode() |
|
157 | ws = NotebookNode() | |
157 | if name is not None: |
|
158 | if name is not None: | |
158 | ws.name = unicode(name) |
|
159 | ws.name = cast_unicode(name) | |
159 | if cells is None: |
|
160 | if cells is None: | |
160 | ws.cells = [] |
|
161 | ws.cells = [] | |
161 | else: |
|
162 | else: | |
@@ -178,7 +179,7 b' def new_notebook(name=None, metadata=None, worksheets=None):' | |||||
178 | else: |
|
179 | else: | |
179 | nb.metadata = NotebookNode(metadata) |
|
180 | nb.metadata = NotebookNode(metadata) | |
180 | if name is not None: |
|
181 | if name is not None: | |
181 | nb.metadata.name = unicode(name) |
|
182 | nb.metadata.name = cast_unicode(name) | |
182 | return nb |
|
183 | return nb | |
183 |
|
184 | |||
184 |
|
185 | |||
@@ -187,29 +188,29 b' def new_metadata(name=None, authors=None, license=None, created=None,' | |||||
187 | """Create a new metadata node.""" |
|
188 | """Create a new metadata node.""" | |
188 | metadata = NotebookNode() |
|
189 | metadata = NotebookNode() | |
189 | if name is not None: |
|
190 | if name is not None: | |
190 | metadata.name = unicode(name) |
|
191 | metadata.name = cast_unicode(name) | |
191 | if authors is not None: |
|
192 | if authors is not None: | |
192 | metadata.authors = list(authors) |
|
193 | metadata.authors = list(authors) | |
193 | if created is not None: |
|
194 | if created is not None: | |
194 | metadata.created = unicode(created) |
|
195 | metadata.created = cast_unicode(created) | |
195 | if modified is not None: |
|
196 | if modified is not None: | |
196 | metadata.modified = unicode(modified) |
|
197 | metadata.modified = cast_unicode(modified) | |
197 | if license is not None: |
|
198 | if license is not None: | |
198 | metadata.license = unicode(license) |
|
199 | metadata.license = cast_unicode(license) | |
199 | if gistid is not None: |
|
200 | if gistid is not None: | |
200 | metadata.gistid = unicode(gistid) |
|
201 | metadata.gistid = cast_unicode(gistid) | |
201 | return metadata |
|
202 | return metadata | |
202 |
|
203 | |||
203 | def new_author(name=None, email=None, affiliation=None, url=None): |
|
204 | def new_author(name=None, email=None, affiliation=None, url=None): | |
204 | """Create a new author.""" |
|
205 | """Create a new author.""" | |
205 | author = NotebookNode() |
|
206 | author = NotebookNode() | |
206 | if name is not None: |
|
207 | if name is not None: | |
207 | author.name = unicode(name) |
|
208 | author.name = cast_unicode(name) | |
208 | if email is not None: |
|
209 | if email is not None: | |
209 | author.email = unicode(email) |
|
210 | author.email = cast_unicode(email) | |
210 | if affiliation is not None: |
|
211 | if affiliation is not None: | |
211 | author.affiliation = unicode(affiliation) |
|
212 | author.affiliation = cast_unicode(affiliation) | |
212 | if url is not None: |
|
213 | if url is not None: | |
213 | author.url = unicode(url) |
|
214 | author.url = cast_unicode(url) | |
214 | return author |
|
215 | return author | |
215 |
|
216 |
@@ -46,7 +46,7 b' class JSONReader(NotebookReader):' | |||||
46 | return nb |
|
46 | return nb | |
47 |
|
47 | |||
48 | def to_notebook(self, d, **kwargs): |
|
48 | def to_notebook(self, d, **kwargs): | |
49 |
return |
|
49 | return rejoin_lines(from_dict(d)) | |
50 |
|
50 | |||
51 |
|
51 | |||
52 | class JSONWriter(NotebookWriter): |
|
52 | class JSONWriter(NotebookWriter): |
@@ -190,7 +190,7 b' class PyWriter(NotebookWriter):' | |||||
190 | lines.extend([u'# ' + line for line in input.splitlines()]) |
|
190 | lines.extend([u'# ' + line for line in input.splitlines()]) | |
191 | lines.append(u'') |
|
191 | lines.append(u'') | |
192 | lines.append('') |
|
192 | lines.append('') | |
193 |
return u |
|
193 | return u'\n'.join(lines) | |
194 |
|
194 | |||
195 |
|
195 | |||
196 | _reader = PyReader() |
|
196 | _reader = PyReader() |
@@ -32,6 +32,8 b' def restore_bytes(nb):' | |||||
32 |
|
32 | |||
33 | Base64 encoding is handled elsewhere. Bytes objects in the notebook are |
|
33 | Base64 encoding is handled elsewhere. Bytes objects in the notebook are | |
34 | always b64-encoded. We DO NOT encode/decode around file formats. |
|
34 | always b64-encoded. We DO NOT encode/decode around file formats. | |
|
35 | ||||
|
36 | Note: this is never used | |||
35 | """ |
|
37 | """ | |
36 | for ws in nb.worksheets: |
|
38 | for ws in nb.worksheets: | |
37 | for cell in ws.cells: |
|
39 | for cell in ws.cells: |
@@ -9,9 +9,9 b' from ..nbbase import (' | |||||
9 | new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor |
|
9 | new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor | |
10 | ) |
|
10 | ) | |
11 |
|
11 | |||
12 |
# some random base64-encoded * |
|
12 | # some random base64-encoded *text* | |
13 | png = encodestring(os.urandom(5)) |
|
13 | png = encodestring(os.urandom(5)).decode('ascii') | |
14 | jpeg = encodestring(os.urandom(6)) |
|
14 | jpeg = encodestring(os.urandom(6)).decode('ascii') | |
15 |
|
15 | |||
16 | ws = new_worksheet(name='worksheet1') |
|
16 | ws = new_worksheet(name='worksheet1') | |
17 |
|
17 |
@@ -1,4 +1,5 b'' | |||||
1 | import pprint |
|
1 | import pprint | |
|
2 | from base64 import decodestring | |||
2 | from unittest import TestCase |
|
3 | from unittest import TestCase | |
3 |
|
4 | |||
4 | from ..nbjson import reads, writes |
|
5 | from ..nbjson import reads, writes | |
@@ -29,5 +30,42 b' class TestJSON(formattest.NBFormatTest, TestCase):' | |||||
29 | s = writes(nb0, split_lines=True) |
|
30 | s = writes(nb0, split_lines=True) | |
30 | self.assertEqual(nbjson.reads(s),nb0) |
|
31 | self.assertEqual(nbjson.reads(s),nb0) | |
31 |
|
32 | |||
|
33 | def test_read_png(self): | |||
|
34 | """PNG output data is b64 unicode""" | |||
|
35 | s = writes(nb0) | |||
|
36 | nb1 = nbjson.reads(s) | |||
|
37 | found_png = False | |||
|
38 | for cell in nb1.worksheets[0].cells: | |||
|
39 | if not 'outputs' in cell: | |||
|
40 | continue | |||
|
41 | for output in cell.outputs: | |||
|
42 | if 'png' in output: | |||
|
43 | found_png = True | |||
|
44 | pngdata = output['png'] | |||
|
45 | self.assertEqual(type(pngdata), unicode) | |||
|
46 | # test that it is valid b64 data | |||
|
47 | b64bytes = pngdata.encode('ascii') | |||
|
48 | raw_bytes = decodestring(b64bytes) | |||
|
49 | assert found_png, "never found png output" | |||
|
50 | ||||
|
51 | def test_read_jpeg(self): | |||
|
52 | """JPEG output data is b64 unicode""" | |||
|
53 | s = writes(nb0) | |||
|
54 | nb1 = nbjson.reads(s) | |||
|
55 | found_jpeg = False | |||
|
56 | for cell in nb1.worksheets[0].cells: | |||
|
57 | if not 'outputs' in cell: | |||
|
58 | continue | |||
|
59 | for output in cell.outputs: | |||
|
60 | if 'jpeg' in output: | |||
|
61 | found_jpeg = True | |||
|
62 | jpegdata = output['jpeg'] | |||
|
63 | self.assertEqual(type(jpegdata), unicode) | |||
|
64 | # test that it is valid b64 data | |||
|
65 | b64bytes = jpegdata.encode('ascii') | |||
|
66 | raw_bytes = decodestring(b64bytes) | |||
|
67 | assert found_jpeg, "never found jpeg output" | |||
|
68 | ||||
|
69 | ||||
32 |
|
70 | |||
33 |
|
71 |
@@ -141,3 +141,17 b' class TestMetadata(TestCase):' | |||||
141 | self.assertEqual(md.gistid, u'21341231') |
|
141 | self.assertEqual(md.gistid, u'21341231') | |
142 | self.assertEqual(md.authors, authors) |
|
142 | self.assertEqual(md.authors, authors) | |
143 |
|
143 | |||
|
144 | class TestOutputs(TestCase): | |||
|
145 | def test_binary_png(self): | |||
|
146 | out = new_output(output_png=b'\x89PNG\r\n\x1a\n') | |||
|
147 | ||||
|
148 | def test_b64b6tes_png(self): | |||
|
149 | out = new_output(output_png=b'iVBORw0KG') | |||
|
150 | ||||
|
151 | def test_binary_jpeg(self): | |||
|
152 | out = new_output(output_jpeg=b'\xff\xd8') | |||
|
153 | ||||
|
154 | def test_b64b6tes_jpeg(self): | |||
|
155 | out = new_output(output_jpeg=b'/9') | |||
|
156 | ||||
|
157 |
General Comments 0
You need to be logged in to leave comments.
Login now