##// END OF EJS Templates
Fix handling of raw cells in all converters, add stderr to test nb
Fernando Perez -
Show More
@@ -1,640 +1,682 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """Convert IPython notebooks to other formats, such as ReST, and HTML.
2 """Convert IPython notebooks to other formats, such as ReST, and HTML.
3
3
4 Example:
4 Example:
5 ./nbconvert.py --format html file.ipynb
5 ./nbconvert.py --format html file.ipynb
6
6
7 Produces 'file.rst' and 'file.html', along with auto-generated figure files
7 Produces 'file.rst' and 'file.html', along with auto-generated figure files
8 called nb_figure_NN.png. To avoid the two-step process, ipynb -> rst -> html,
8 called nb_figure_NN.png. To avoid the two-step process, ipynb -> rst -> html,
9 use '--format quick-html' which will do ipynb -> html, but won't look as
9 use '--format quick-html' which will do ipynb -> html, but won't look as
10 pretty.
10 pretty.
11 """
11 """
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 import codecs
14 import codecs
15 import logging
15 import os
16 import os
16 import pprint
17 import pprint
17 import re
18 import re
18 import subprocess
19 import subprocess
19 import sys
20 import sys
20
21
21 from IPython.external import argparse
22 from IPython.external import argparse
22 from IPython.nbformat import current as nbformat
23 from IPython.nbformat import current as nbformat
23 from IPython.utils.text import indent
24 from IPython.utils.text import indent
24 from decorators import DocInherit
25 from decorators import DocInherit
25
26
26 def remove_ansi(src):
27 def remove_ansi(src):
27 """Strip all ANSI color escape sequences from input string.
28 """Strip all ANSI color escape sequences from input string.
28
29
29 Parameters
30 Parameters
30 ----------
31 ----------
31 src : string
32 src : string
32
33
33 Returns
34 Returns
34 -------
35 -------
35 string
36 string
36 """
37 """
37 return re.sub(r'\033\[(0|\d;\d\d)m', '', src)
38 return re.sub(r'\033\[(0|\d;\d\d)m', '', src)
38
39
39 # Pandoc-dependent code
40 # Pandoc-dependent code
40 def markdown2latex(src):
41 def markdown2latex(src):
41 """Convert a markdown string to LaTeX via pandoc.
42 """Convert a markdown string to LaTeX via pandoc.
42
43
43 This function will raise an error if pandoc is not installed.
44 This function will raise an error if pandoc is not installed.
44
45
45 Any error messages generated by pandoc are printed to stderr.
46 Any error messages generated by pandoc are printed to stderr.
46
47
47 Parameters
48 Parameters
48 ----------
49 ----------
49 src : string
50 src : string
50 Input string, assumed to be valid markdown.
51 Input string, assumed to be valid markdown.
51
52
52 Returns
53 Returns
53 -------
54 -------
54 out : string
55 out : string
55 Output as returned by pandoc.
56 Output as returned by pandoc.
56 """
57 """
57 p = subprocess.Popen('pandoc -f markdown -t latex'.split(),
58 p = subprocess.Popen('pandoc -f markdown -t latex'.split(),
58 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
59 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
59 out, err = p.communicate(src)
60 out, err = p.communicate(src)
60 if err:
61 if err:
61 print(err, file=sys.stderr)
62 print(err, file=sys.stderr)
62 #print('*'*20+'\n', out, '\n'+'*'*20) # dbg
63 #print('*'*20+'\n', out, '\n'+'*'*20) # dbg
63 return out
64 return out
64
65
65 # Cell converters
66 # Cell converters
66
67
67
68
68 def rst_directive(directive, text=''):
69 def rst_directive(directive, text=''):
69 out = [directive, '']
70 out = [directive, '']
70 if text:
71 if text:
71 out.extend([indent(text), ''])
72 out.extend([indent(text), ''])
72 return out
73 return out
73
74
74 # Converters for parts of a cell.
75 # Converters for parts of a cell.
75
76
76
77
77 class ConversionException(Exception):
78 class ConversionException(Exception):
78 pass
79 pass
79
80
80
81
81 class Converter(object):
82 class Converter(object):
82 default_encoding = 'utf-8'
83 default_encoding = 'utf-8'
83 extension = str()
84 extension = str()
84 figures_counter = 0
85 figures_counter = 0
85 infile = str()
86 infile = str()
86 infile_dir = str()
87 infile_dir = str()
87 infile_root = str()
88 infile_root = str()
88 files_dir = str()
89 files_dir = str()
89 with_preamble = True
90 with_preamble = True
90 user_preamble = None
91 user_preamble = None
91 output = str()
92 output = str()
93 raw_as_verbatim = False
92
94
93 def __init__(self, infile):
95 def __init__(self, infile):
94 self.infile = infile
96 self.infile = infile
95 self.infile_dir = os.path.dirname(infile)
97 self.infile_dir = os.path.dirname(infile)
96 infile_root = os.path.splitext(infile)[0]
98 infile_root = os.path.splitext(infile)[0]
97 files_dir = infile_root + '_files'
99 files_dir = infile_root + '_files'
98 if not os.path.isdir(files_dir):
100 if not os.path.isdir(files_dir):
99 os.mkdir(files_dir)
101 os.mkdir(files_dir)
100 self.infile_root = infile_root
102 self.infile_root = infile_root
101 self.files_dir = files_dir
103 self.files_dir = files_dir
102
104
103 def dispatch(self, cell_type):
105 def dispatch(self, cell_type):
104 """return cell_type dependent render method, for example render_code
106 """return cell_type dependent render method, for example render_code
105 """
107 """
106 return getattr(self, 'render_' + cell_type, self.render_unknown)
108 return getattr(self, 'render_' + cell_type, self.render_unknown)
107
109
108 def convert(self):
110 def convert(self):
109 lines = []
111 lines = []
110 lines.extend(self.optional_header())
112 lines.extend(self.optional_header())
111 for worksheet in self.nb.worksheets:
113 for worksheet in self.nb.worksheets:
112 for cell in worksheet.cells:
114 for cell in worksheet.cells:
115 #print(cell.cell_type) # dbg
113 conv_fn = self.dispatch(cell.cell_type)
116 conv_fn = self.dispatch(cell.cell_type)
114 lines.extend(conv_fn(cell))
117 lines.extend(conv_fn(cell))
115 lines.append('')
118 lines.append('')
116 lines.extend(self.optional_footer())
119 lines.extend(self.optional_footer())
117 return '\n'.join(lines)
120 return '\n'.join(lines)
118
121
119 def render(self):
122 def render(self):
120 "read, convert, and save self.infile"
123 "read, convert, and save self.infile"
121 self.read()
124 self.read()
122 self.output = self.convert()
125 self.output = self.convert()
123 return self.save()
126 return self.save()
124
127
125 def read(self):
128 def read(self):
126 "read and parse notebook into NotebookNode called self.nb"
129 "read and parse notebook into NotebookNode called self.nb"
127 with open(self.infile) as f:
130 with open(self.infile) as f:
128 self.nb = nbformat.read(f, 'json')
131 self.nb = nbformat.read(f, 'json')
129
132
130 def save(self, infile=None, encoding=None):
133 def save(self, infile=None, encoding=None):
131 "read and parse notebook into self.nb"
134 "read and parse notebook into self.nb"
132 if infile is None:
135 if infile is None:
133 infile = os.path.splitext(self.infile)[0] + '.' + self.extension
136 infile = os.path.splitext(self.infile)[0] + '.' + self.extension
134 if encoding is None:
137 if encoding is None:
135 encoding = self.default_encoding
138 encoding = self.default_encoding
136 with open(infile, 'w') as f:
139 with open(infile, 'w') as f:
137 f.write(self.output.encode(encoding))
140 f.write(self.output.encode(encoding))
138 return infile
141 return infile
139
142
140 def optional_header(self):
143 def optional_header(self):
141 return []
144 return []
142
145
143 def optional_footer(self):
146 def optional_footer(self):
144 return []
147 return []
145
148
146 def _new_figure(self, data, fmt):
149 def _new_figure(self, data, fmt):
147 """Create a new figure file in the given format.
150 """Create a new figure file in the given format.
148
151
149 Returns a path relative to the input file.
152 Returns a path relative to the input file.
150 """
153 """
151 figname = '%s_fig_%02i.%s' % (self.infile_root,
154 figname = '%s_fig_%02i.%s' % (self.infile_root,
152 self.figures_counter, fmt)
155 self.figures_counter, fmt)
153 self.figures_counter += 1
156 self.figures_counter += 1
154 fullname = os.path.join(self.files_dir, figname)
157 fullname = os.path.join(self.files_dir, figname)
155
158
156 # Binary files are base64-encoded, SVG is already XML
159 # Binary files are base64-encoded, SVG is already XML
157 if fmt in ('png', 'jpg', 'pdf'):
160 if fmt in ('png', 'jpg', 'pdf'):
158 data = data.decode('base64')
161 data = data.decode('base64')
159 fopen = lambda fname: open(fname, 'wb')
162 fopen = lambda fname: open(fname, 'wb')
160 else:
163 else:
161 fopen = lambda fname: codecs.open(fname, 'wb', self.default_encoding)
164 fopen = lambda fname: codecs.open(fname, 'wb', self.default_encoding)
162
165
163 with fopen(fullname) as f:
166 with fopen(fullname) as f:
164 f.write(data)
167 f.write(data)
165
168
166 return fullname
169 return fullname
167
170
168 def render_heading(self, cell):
171 def render_heading(self, cell):
169 """convert a heading cell
172 """convert a heading cell
170
173
171 Returns list."""
174 Returns list."""
172 raise NotImplementedError
175 raise NotImplementedError
173
176
174 def render_code(self, cell):
177 def render_code(self, cell):
175 """Convert a code cell
178 """Convert a code cell
176
179
177 Returns list."""
180 Returns list."""
178 raise NotImplementedError
181 raise NotImplementedError
179
182
180 def render_markdown(self, cell):
183 def render_markdown(self, cell):
181 """convert a markdown cell
184 """convert a markdown cell
182
185
183 Returns list."""
186 Returns list."""
184 raise NotImplementedError
187 raise NotImplementedError
185
188
186 def render_pyout(self, output):
189 def render_pyout(self, output):
187 """convert pyout part of a code cell
190 """convert pyout part of a code cell
188
191
189 Returns list."""
192 Returns list."""
190 raise NotImplementedError
193 raise NotImplementedError
191
194
192
195
193 def render_pyerr(self, output):
196 def render_pyerr(self, output):
194 """convert pyerr part of a code cell
197 """convert pyerr part of a code cell
195
198
196 Returns list."""
199 Returns list."""
197 raise NotImplementedError
200 raise NotImplementedError
198
201
199 def _img_lines(self, img_file):
202 def _img_lines(self, img_file):
200 """Return list of lines to include an image file."""
203 """Return list of lines to include an image file."""
201 # Note: subclasses may choose to implement format-specific _FMT_lines
204 # Note: subclasses may choose to implement format-specific _FMT_lines
202 # methods if they so choose (FMT in {png, svg, jpg, pdf}).
205 # methods if they so choose (FMT in {png, svg, jpg, pdf}).
203 raise NotImplementedError
206 raise NotImplementedError
204
207
205 def render_display_data(self, output):
208 def render_display_data(self, output):
206 """convert display data from the output of a code cell
209 """convert display data from the output of a code cell
207
210
208 Returns list.
211 Returns list.
209 """
212 """
210 lines = []
213 lines = []
211
214
212 for fmt in ['png', 'svg', 'jpg', 'pdf']:
215 for fmt in ['png', 'svg', 'jpg', 'pdf']:
213 if fmt in output:
216 if fmt in output:
214 img_file = self._new_figure(output[fmt], fmt)
217 img_file = self._new_figure(output[fmt], fmt)
215 # Subclasses can have format-specific render functions (e.g.,
218 # Subclasses can have format-specific render functions (e.g.,
216 # latex has to auto-convert all SVG to PDF first).
219 # latex has to auto-convert all SVG to PDF first).
217 lines_fun = getattr(self, '_%s_lines' % fmt, None)
220 lines_fun = getattr(self, '_%s_lines' % fmt, None)
218 if not lines_fun:
221 if not lines_fun:
219 lines_fun = self._img_lines
222 lines_fun = self._img_lines
220 lines.extend(lines_fun(img_file))
223 lines.extend(lines_fun(img_file))
221
224
222 return lines
225 return lines
223
226
224 def render_stream(self, cell):
227 def render_stream(self, cell):
225 """convert stream part of a code cell
228 """convert stream part of a code cell
226
229
227 Returns list."""
230 Returns list."""
228 raise NotImplementedError
231 raise NotImplementedError
229
232
230 def render_plaintext(self, cell):
233 def render_raw(self, cell):
231 """convert plain text
234 """convert a cell with raw text
232
235
233 Returns list."""
236 Returns list."""
234 raise NotImplementedError
237 raise NotImplementedError
235
238
236 def render_unknown(self, cell):
239 def render_unknown(self, cell):
237 """Render cells of unkown type
240 """Render cells of unkown type
238
241
239 Returns list."""
242 Returns list."""
243 data = pprint.pformat(cell)
244 logging.warning('Unknown cell:\n%s' % data)
245 return self._unknown_lines(data)
246
247 def _unknown_lines(self, data):
248 """Return list of lines for an unknown cell.
249
250 Parameters
251 ----------
252 data : str
253 The content of the unknown data as a single string.
254 """
240 raise NotImplementedError
255 raise NotImplementedError
241
256
242
257
243 class ConverterRST(Converter):
258 class ConverterRST(Converter):
244 extension = 'rst'
259 extension = 'rst'
245 heading_level = {1: '=', 2: '-', 3: '`', 4: '\'', 5: '.', 6: '~'}
260 heading_level = {1: '=', 2: '-', 3: '`', 4: '\'', 5: '.', 6: '~'}
246
261
247 @DocInherit
262 @DocInherit
248 def render_heading(self, cell):
263 def render_heading(self, cell):
249 marker = self.heading_level[cell.level]
264 marker = self.heading_level[cell.level]
250 return ['{0}\n{1}\n'.format(cell.source, marker * len(cell.source))]
265 return ['{0}\n{1}\n'.format(cell.source, marker * len(cell.source))]
251
266
252 @DocInherit
267 @DocInherit
253 def render_code(self, cell):
268 def render_code(self, cell):
254 if not cell.input:
269 if not cell.input:
255 return []
270 return []
256
271
257 lines = ['In[%s]:' % cell.prompt_number, '']
272 lines = ['In[%s]:' % cell.prompt_number, '']
258 lines.extend(rst_directive('.. code:: python', cell.input))
273 lines.extend(rst_directive('.. code:: python', cell.input))
259
274
260 for output in cell.outputs:
275 for output in cell.outputs:
261 conv_fn = self.dispatch(output.output_type)
276 conv_fn = self.dispatch(output.output_type)
262 lines.extend(conv_fn(output))
277 lines.extend(conv_fn(output))
263
278
264 return lines
279 return lines
265
280
266 @DocInherit
281 @DocInherit
267 def render_markdown(self, cell):
282 def render_markdown(self, cell):
268 return [cell.source]
283 return [cell.source]
269
284
270 @DocInherit
285 @DocInherit
271 def render_plaintext(self, cell):
286 def render_raw(self, cell):
272 return [cell.source]
287 if self.raw_as_verbatim:
288 return ['::', '', indent(cell.source), '']
289 else:
290 return [cell.source]
273
291
274 @DocInherit
292 @DocInherit
275 def render_pyout(self, output):
293 def render_pyout(self, output):
276 lines = ['Out[%s]:' % output.prompt_number, '']
294 lines = ['Out[%s]:' % output.prompt_number, '']
277
295
278 # output is a dictionary like object with type as a key
296 # output is a dictionary like object with type as a key
279 if 'latex' in output:
297 if 'latex' in output:
280 lines.extend(rst_directive('.. math::', output.latex))
298 lines.extend(rst_directive('.. math::', output.latex))
281
299
282 if 'text' in output:
300 if 'text' in output:
283 lines.extend(rst_directive('.. parsed-literal::', output.text))
301 lines.extend(rst_directive('.. parsed-literal::', output.text))
284
302
285 return lines
303 return lines
286
304
287 @DocInherit
305 @DocInherit
306 def render_pyerr(self, output):
307 # Note: a traceback is a *list* of frames.
308 return ['::', '', indent(remove_ansi('\n'.join(output.traceback))), '']
309
310 @DocInherit
288 def _img_lines(self, img_file):
311 def _img_lines(self, img_file):
289 return ['.. image:: %s' % img_file, '']
312 return ['.. image:: %s' % img_file, '']
290
313
291 @DocInherit
314 @DocInherit
292 def render_stream(self, output):
315 def render_stream(self, output):
293 lines = []
316 lines = []
294
317
295 if 'text' in output:
318 if 'text' in output:
296 lines.extend(rst_directive('.. parsed-literal::', output.text))
319 lines.extend(rst_directive('.. parsed-literal::', output.text))
297
320
298 return lines
321 return lines
299
322
300 @DocInherit
323 @DocInherit
301 def render_unknown(self, cell):
324 def _unknown_lines(self, data):
302 return rst_directive('.. warning:: Unknown cell') + [repr(cell)]
325 return rst_directive('.. warning:: Unknown cell') + [data]
303
326
304
327
305 class ConverterQuickHTML(Converter):
328 class ConverterQuickHTML(Converter):
306 extension = 'html'
329 extension = 'html'
307
330
331 def in_tag(self, tag, src):
332 """Return a list of elements bracketed by the given tag"""
333 return ['<%s>' % tag, src, '</%s>' % tag]
334
308 def optional_header(self):
335 def optional_header(self):
309 # XXX: inject the IPython standard CSS into here
336 # XXX: inject the IPython standard CSS into here
310 s = """<html>
337 s = """<html>
311 <head>
338 <head>
312 </head>
339 </head>
313
340
314 <body>
341 <body>
315 """
342 """
316 return s.splitlines()
343 return s.splitlines()
317
344
318 def optional_footer(self):
345 def optional_footer(self):
319 s = """</body>
346 s = """</body>
320 </html>
347 </html>
321 """
348 """
322 return s.splitlines()
349 return s.splitlines()
323
350
324 @DocInherit
351 @DocInherit
325 def render_heading(self, cell):
352 def render_heading(self, cell):
326 marker = cell.level
353 marker = cell.level
327 return ['<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
354 return ['<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
328
355
329 @DocInherit
356 @DocInherit
330 def render_code(self, cell):
357 def render_code(self, cell):
331 if not cell.input:
358 if not cell.input:
332 return []
359 return []
333
360
334 lines = ['<table>']
361 lines = ['<table>']
335 lines.append('<tr><td><tt>In [<b>%s</b>]:</tt></td><td><tt>' % cell.prompt_number)
362 lines.append('<tr><td><tt>In [<b>%s</b>]:</tt></td><td><tt>' % cell.prompt_number)
336 lines.append("<br>\n".join(cell.input.splitlines()))
363 lines.append("<br>\n".join(cell.input.splitlines()))
337 lines.append('</tt></td></tr>')
364 lines.append('</tt></td></tr>')
338
365
339 for output in cell.outputs:
366 for output in cell.outputs:
340 lines.append('<tr><td></td><td>')
367 lines.append('<tr><td></td><td>')
341 conv_fn = self.dispatch(output.output_type)
368 conv_fn = self.dispatch(output.output_type)
342 lines.extend(conv_fn(output))
369 lines.extend(conv_fn(output))
343 lines.append('</td></tr>')
370 lines.append('</td></tr>')
344
371
345 lines.append('</table>')
372 lines.append('</table>')
346 return lines
373 return lines
347
374
348 @DocInherit
375 @DocInherit
349 def render_markdown(self, cell):
376 def render_markdown(self, cell):
350 return ["<pre>"+cell.source+"</pre>"]
377 return self.in_tag('pre', cell.source)
351
378
352 @DocInherit
379 @DocInherit
353 def render_plaintext(self, cell):
380 def render_raw(self, cell):
354 return ["<pre>"+cell.source+"</pre>"]
381 if self.raw_as_verbatim:
382 return self.in_tag('pre', cell.source)
383 else:
384 return [cell.source]
355
385
356 @DocInherit
386 @DocInherit
357 def render_pyout(self, output):
387 def render_pyout(self, output):
358 lines = ['<tr><td><tt>Out[<b>%s</b>]:</tt></td></tr>' % output.prompt_number, '<td>']
388 lines = ['<tr><td><tt>Out[<b>%s</b>]:</tt></td></tr>' %
389 output.prompt_number, '<td>']
359
390
360 # output is a dictionary like object with type as a key
391 # output is a dictionary like object with type as a key
361 if 'latex' in output:
392 for out_type in ('text', 'latex'):
362 lines.append("<pre>")
393 if out_type in output:
363 lines.extend(indent(output.latex))
394 lines.extend(self.in_tag('pre', indent(output[out_type])))
364 lines.append("</pre>")
365
366 if 'text' in output:
367 lines.append("<pre>")
368 lines.extend(indent(output.text))
369 lines.append("</pre>")
370
395
371 return lines
396 return lines
372
397
373 @DocInherit
398 @DocInherit
399 def render_pyerr(self, output):
400 # Note: a traceback is a *list* of frames.
401 return self.in_tag('pre', remove_ansi('\n'.join(output.traceback)))
402
403 @DocInherit
374 def _img_lines(self, img_file):
404 def _img_lines(self, img_file):
375 return ['<img src="%s">' % img_file, '']
405 return ['<img src="%s">' % img_file, '']
376
406
377 @DocInherit
407 @DocInherit
378 def render_stream(self, output):
408 def render_stream(self, output):
379 lines = []
409 lines = []
380
410
381 if 'text' in output:
411 if 'text' in output:
382 lines.append(output.text)
412 lines.append(output.text)
383
413
384 return lines
414 return lines
385
415
416 @DocInherit
417 def _unknown_lines(self, data):
418 return ['<h2>Warning:: Unknown cell</h2>'] + self.in_tag('pre', data)
419
386
420
387 class ConverterLaTeX(Converter):
421 class ConverterLaTeX(Converter):
388 """Converts a notebook to a .tex file suitable for pdflatex.
422 """Converts a notebook to a .tex file suitable for pdflatex.
389
423
390 Note: this converter *needs*:
424 Note: this converter *needs*:
391
425
392 - `pandoc`: for all conversion of markdown cells. If your notebook only
426 - `pandoc`: for all conversion of markdown cells. If your notebook only
393 has Raw cells, pandoc will not be needed.
427 has Raw cells, pandoc will not be needed.
394
428
395 - `inkscape`: if your notebook has SVG figures. These need to be
429 - `inkscape`: if your notebook has SVG figures. These need to be
396 converted to PDF before inclusion in the TeX file, as LaTeX doesn't
430 converted to PDF before inclusion in the TeX file, as LaTeX doesn't
397 understand SVG natively.
431 understand SVG natively.
398
432
399 You will in general obtain much better final PDF results if you configure
433 You will in general obtain much better final PDF results if you configure
400 the matplotlib backend to create SVG output with
434 the matplotlib backend to create SVG output with
401
435
402 %config InlineBackend.figure_format = 'svg'
436 %config InlineBackend.figure_format = 'svg'
403
437
404 (or set the equivalent flag at startup or in your configuration profile).
438 (or set the equivalent flag at startup or in your configuration profile).
405 """
439 """
406 extension = 'tex'
440 extension = 'tex'
407 documentclass = 'article'
441 documentclass = 'article'
408 documentclass_options = '11pt,english'
442 documentclass_options = '11pt,english'
409 heading_map = {1: r'\section',
443 heading_map = {1: r'\section',
410 2: r'\subsection',
444 2: r'\subsection',
411 3: r'\subsubsection',
445 3: r'\subsubsection',
412 4: r'\paragraph',
446 4: r'\paragraph',
413 5: r'\subparagraph',
447 5: r'\subparagraph',
414 6: r'\subparagraph'}
448 6: r'\subparagraph'}
415
449
416 def env(self, environment, lines):
450 def in_env(self, environment, lines):
417 """Return list of environment lines for input lines
451 """Return list of environment lines for input lines
418
452
419 Parameters
453 Parameters
420 ----------
454 ----------
421 env : string
455 env : string
422 Name of the environment to bracket with begin/end.
456 Name of the environment to bracket with begin/end.
423
457
424 lines: """
458 lines: """
425 out = [r'\begin{%s}' % environment]
459 out = [r'\begin{%s}' % environment]
426 if isinstance(lines, basestring):
460 if isinstance(lines, basestring):
427 out.append(lines)
461 out.append(lines)
428 else: # list
462 else: # list
429 out.extend(lines)
463 out.extend(lines)
430 out.append(r'\end{%s}' % environment)
464 out.append(r'\end{%s}' % environment)
431 return out
465 return out
432
466
433 def convert(self):
467 def convert(self):
434 # The main body is done by the logic in the parent class, and that's
468 # The main body is done by the logic in the parent class, and that's
435 # all we need if preamble support has been turned off.
469 # all we need if preamble support has been turned off.
436 body = super(ConverterLaTeX, self).convert()
470 body = super(ConverterLaTeX, self).convert()
437 if not self.with_preamble:
471 if not self.with_preamble:
438 return body
472 return body
439 # But if preamble is on, then we need to construct a proper, standalone
473 # But if preamble is on, then we need to construct a proper, standalone
440 # tex file.
474 # tex file.
441
475
442 # Tag the document at the top and set latex class
476 # Tag the document at the top and set latex class
443 final = [ r'%% This file was auto-generated by IPython, do NOT edit',
477 final = [ r'%% This file was auto-generated by IPython, do NOT edit',
444 r'%% Conversion from the original notebook file:',
478 r'%% Conversion from the original notebook file:',
445 r'%% {0}'.format(self.infile),
479 r'%% {0}'.format(self.infile),
446 r'%%',
480 r'%%',
447 r'\documentclass[%s]{%s}' % (self.documentclass_options,
481 r'\documentclass[%s]{%s}' % (self.documentclass_options,
448 self.documentclass),
482 self.documentclass),
449 '',
483 '',
450 ]
484 ]
451 # Load our own preamble, which is stored next to the main file. We
485 # Load our own preamble, which is stored next to the main file. We
452 # need to be careful in case the script entry point is a symlink
486 # need to be careful in case the script entry point is a symlink
453 myfile = __file__ if not os.path.islink(__file__) else \
487 myfile = __file__ if not os.path.islink(__file__) else \
454 os.readlink(__file__)
488 os.readlink(__file__)
455 with open(os.path.join(os.path.dirname(myfile), 'preamble.tex')) as f:
489 with open(os.path.join(os.path.dirname(myfile), 'preamble.tex')) as f:
456 final.append(f.read())
490 final.append(f.read())
457
491
458 # Load any additional user-supplied preamble
492 # Load any additional user-supplied preamble
459 if self.user_preamble:
493 if self.user_preamble:
460 final.extend(['', '%% Adding user preamble from file:',
494 final.extend(['', '%% Adding user preamble from file:',
461 '%% {0}'.format(self.user_preamble), ''])
495 '%% {0}'.format(self.user_preamble), ''])
462 with open(self.user_preamble) as f:
496 with open(self.user_preamble) as f:
463 final.append(f.read())
497 final.append(f.read())
464
498
465 # Include document body
499 # Include document body
466 final.extend([ r'\begin{document}', '',
500 final.extend([ r'\begin{document}', '',
467 body,
501 body,
468 r'\end{document}', ''])
502 r'\end{document}', ''])
469 # Retun value must be a string
503 # Retun value must be a string
470 return '\n'.join(final)
504 return '\n'.join(final)
471
505
472 @DocInherit
506 @DocInherit
473 def render_heading(self, cell):
507 def render_heading(self, cell):
474 marker = self.heading_map[cell.level]
508 marker = self.heading_map[cell.level]
475 return ['%s{%s}\n\n' % (marker, cell.source) ]
509 return ['%s{%s}\n\n' % (marker, cell.source) ]
476
510
477 @DocInherit
511 @DocInherit
478 def render_code(self, cell):
512 def render_code(self, cell):
479 if not cell.input:
513 if not cell.input:
480 return []
514 return []
481
515
482 # Cell codes first carry input code, we use lstlisting for that
516 # Cell codes first carry input code, we use lstlisting for that
483 lines = [r'\begin{codecell}']
517 lines = [r'\begin{codecell}']
484
518
485 lines.extend(self.env('codeinput',
519 lines.extend(self.in_env('codeinput',
486 self.env('lstlisting', cell.input)))
520 self.in_env('lstlisting', cell.input)))
487
521
488 outlines = []
522 outlines = []
489 for output in cell.outputs:
523 for output in cell.outputs:
490 conv_fn = self.dispatch(output.output_type)
524 conv_fn = self.dispatch(output.output_type)
491 outlines.extend(conv_fn(output))
525 outlines.extend(conv_fn(output))
492
526
493 # And then output of many possible types; use a frame for all of it.
527 # And then output of many possible types; use a frame for all of it.
494 if outlines:
528 if outlines:
495 lines.extend(self.env('codeoutput', outlines))
529 lines.extend(self.in_env('codeoutput', outlines))
496
530
497 lines.append(r'\end{codecell}')
531 lines.append(r'\end{codecell}')
498
532
499 return lines
533 return lines
500
534
501
535
502 @DocInherit
536 @DocInherit
503 def _img_lines(self, img_file):
537 def _img_lines(self, img_file):
504 return self.env('center',
538 return self.in_env('center',
505 [r'\includegraphics[width=3in]{%s}' % img_file, r'\par'])
539 [r'\includegraphics[width=3in]{%s}' % img_file, r'\par'])
506
540
507 def _svg_lines(self, img_file):
541 def _svg_lines(self, img_file):
508 base_file = os.path.splitext(img_file)[0]
542 base_file = os.path.splitext(img_file)[0]
509 pdf_file = base_file + '.pdf'
543 pdf_file = base_file + '.pdf'
510 subprocess.check_call(['inkscape', '--export-pdf=%s' % pdf_file,
544 subprocess.check_call(['inkscape', '--export-pdf=%s' % pdf_file,
511 img_file])
545 img_file])
512 return self._img_lines(pdf_file)
546 return self._img_lines(pdf_file)
513
547
514 @DocInherit
548 @DocInherit
515 def render_stream(self, output):
549 def render_stream(self, output):
516 lines = []
550 lines = []
517
551
518 if 'text' in output:
552 if 'text' in output:
519 lines.extend(self.env('verbatim', output.text.strip()))
553 lines.extend(self.in_env('verbatim', output.text.strip()))
520
554
521 return lines
555 return lines
522
556
523 @DocInherit
557 @DocInherit
524 def render_markdown(self, cell):
558 def render_markdown(self, cell):
525 return [markdown2latex(cell['source'])]
559 return [markdown2latex(cell['source'])]
526
560
527 @DocInherit
561 @DocInherit
528 def render_pyout(self, output):
562 def render_pyout(self, output):
529 lines = []
563 lines = []
530
564
531 # output is a dictionary like object with type as a key
565 # output is a dictionary like object with type as a key
532 if 'latex' in output:
566 if 'latex' in output:
533 lines.extend(output.latex)
567 lines.extend(output.latex)
534
568
535 if 'text' in output:
569 if 'text' in output:
536 lines.extend(self.env('verbatim', output.text))
570 lines.extend(self.in_env('verbatim', output.text))
537
571
538 return lines
572 return lines
539
573
540 @DocInherit
574 @DocInherit
541 def render_pyerr(self, output):
575 def render_pyerr(self, output):
542 # Note: a traceback is a *list* of frames.
576 # Note: a traceback is a *list* of frames.
543 return self.env('traceback',
577 return self.in_env('traceback',
544 self.env('verbatim',
578 self.in_env('verbatim',
545 remove_ansi('\n'.join(output.traceback))))
579 remove_ansi('\n'.join(output.traceback))))
546
580
547 @DocInherit
581 @DocInherit
548 def render_unknown(self, cell):
582 def render_raw(self, cell):
549 return self.env('verbatim', pprint.pformat(cell))
583 if self.raw_as_verbatim:
584 return self.in_env('verbatim', cell.source)
585 else:
586 return [cell.source]
587
588 @DocInherit
589 def _unknown_lines(self, data):
590 return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \
591 self.in_env('verbatim', data)
550
592
551
593
552 def rst2simplehtml(infile):
594 def rst2simplehtml(infile):
553 """Convert a rst file to simplified html suitable for blogger.
595 """Convert a rst file to simplified html suitable for blogger.
554
596
555 This just runs rst2html with certain parameters to produce really simple
597 This just runs rst2html with certain parameters to produce really simple
556 html and strips the document header, so the resulting file can be easily
598 html and strips the document header, so the resulting file can be easily
557 pasted into a blogger edit window.
599 pasted into a blogger edit window.
558 """
600 """
559
601
560 # This is the template for the rst2html call that produces the cleanest,
602 # This is the template for the rst2html call that produces the cleanest,
561 # simplest html I could find. This should help in making it easier to
603 # simplest html I could find. This should help in making it easier to
562 # paste into the blogspot html window, though I'm still having problems
604 # paste into the blogspot html window, though I'm still having problems
563 # with linebreaks there...
605 # with linebreaks there...
564 cmd_template = ("rst2html --link-stylesheet --no-xml-declaration "
606 cmd_template = ("rst2html --link-stylesheet --no-xml-declaration "
565 "--no-generator --no-datestamp --no-source-link "
607 "--no-generator --no-datestamp --no-source-link "
566 "--no-toc-backlinks --no-section-numbering "
608 "--no-toc-backlinks --no-section-numbering "
567 "--strip-comments ")
609 "--strip-comments ")
568
610
569 cmd = "%s %s" % (cmd_template, infile)
611 cmd = "%s %s" % (cmd_template, infile)
570 proc = subprocess.Popen(cmd,
612 proc = subprocess.Popen(cmd,
571 stdout=subprocess.PIPE,
613 stdout=subprocess.PIPE,
572 stderr=subprocess.PIPE,
614 stderr=subprocess.PIPE,
573 shell=True)
615 shell=True)
574 html, stderr = proc.communicate()
616 html, stderr = proc.communicate()
575 if stderr:
617 if stderr:
576 raise IOError(stderr)
618 raise IOError(stderr)
577
619
578 # Make an iterator so breaking out holds state. Our implementation of
620 # Make an iterator so breaking out holds state. Our implementation of
579 # searching for the html body below is basically a trivial little state
621 # searching for the html body below is basically a trivial little state
580 # machine, so we need this.
622 # machine, so we need this.
581 walker = iter(html.splitlines())
623 walker = iter(html.splitlines())
582
624
583 # Find start of main text, break out to then print until we find end /div.
625 # Find start of main text, break out to then print until we find end /div.
584 # This may only work if there's a real title defined so we get a 'div class'
626 # This may only work if there's a real title defined so we get a 'div class'
585 # tag, I haven't really tried.
627 # tag, I haven't really tried.
586 for line in walker:
628 for line in walker:
587 if line.startswith('<body>'):
629 if line.startswith('<body>'):
588 break
630 break
589
631
590 newfname = os.path.splitext(infile)[0] + '.html'
632 newfname = os.path.splitext(infile)[0] + '.html'
591 with open(newfname, 'w') as f:
633 with open(newfname, 'w') as f:
592 for line in walker:
634 for line in walker:
593 if line.startswith('</body>'):
635 if line.startswith('</body>'):
594 break
636 break
595 f.write(line)
637 f.write(line)
596 f.write('\n')
638 f.write('\n')
597
639
598 return newfname
640 return newfname
599
641
600 known_formats = "rst (default), html, quick-html, latex"
642 known_formats = "rst (default), html, quick-html, latex"
601
643
602 def main(infile, format='rst'):
644 def main(infile, format='rst'):
603 """Convert a notebook to html in one step"""
645 """Convert a notebook to html in one step"""
604 # XXX: this is just quick and dirty for now. When adding a new format,
646 # XXX: this is just quick and dirty for now. When adding a new format,
605 # make sure to add it to the `known_formats` string above, which gets
647 # make sure to add it to the `known_formats` string above, which gets
606 # printed in in the catch-all else, as well as in the help
648 # printed in in the catch-all else, as well as in the help
607 if format == 'rst':
649 if format == 'rst':
608 converter = ConverterRST(infile)
650 converter = ConverterRST(infile)
609 converter.render()
651 converter.render()
610 elif format == 'html':
652 elif format == 'html':
611 #Currently, conversion to html is a 2 step process, nb->rst->html
653 #Currently, conversion to html is a 2 step process, nb->rst->html
612 converter = ConverterRST(infile)
654 converter = ConverterRST(infile)
613 rstfname = converter.render()
655 rstfname = converter.render()
614 rst2simplehtml(rstfname)
656 rst2simplehtml(rstfname)
615 elif format == 'quick-html':
657 elif format == 'quick-html':
616 converter = ConverterQuickHTML(infile)
658 converter = ConverterQuickHTML(infile)
617 rstfname = converter.render()
659 rstfname = converter.render()
618 elif format == 'latex':
660 elif format == 'latex':
619 converter = ConverterLaTeX(infile)
661 converter = ConverterLaTeX(infile)
620 latexfname = converter.render()
662 latexfname = converter.render()
621 else:
663 else:
622 raise SystemExit("Unknown format '%s', " % format +
664 raise SystemExit("Unknown format '%s', " % format +
623 "known formats are: " + known_formats)
665 "known formats are: " + known_formats)
624
666
625
667
626
668
627 if __name__ == '__main__':
669 if __name__ == '__main__':
628 parser = argparse.ArgumentParser(description=__doc__,
670 parser = argparse.ArgumentParser(description=__doc__,
629 formatter_class=argparse.RawTextHelpFormatter)
671 formatter_class=argparse.RawTextHelpFormatter)
630 # TODO: consider passing file like object around, rather than filenames
672 # TODO: consider passing file like object around, rather than filenames
631 # would allow us to process stdin, or even http streams
673 # would allow us to process stdin, or even http streams
632 #parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
674 #parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
633
675
634 #Require a filename as a positional argument
676 #Require a filename as a positional argument
635 parser.add_argument('infile', nargs=1)
677 parser.add_argument('infile', nargs=1)
636 parser.add_argument('-f', '--format', default='rst',
678 parser.add_argument('-f', '--format', default='rst',
637 help='Output format. Supported formats: \n' +
679 help='Output format. Supported formats: \n' +
638 known_formats)
680 known_formats)
639 args = parser.parse_args()
681 args = parser.parse_args()
640 main(infile=args.infile[0], format=args.format)
682 main(infile=args.infile[0], format=args.format)
@@ -1,159 +1,210 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": "test"
3 "name": "test"
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
9 {
9 {
10 "cell_type": "heading",
10 "cell_type": "heading",
11 "level": 1,
11 "level": 1,
12 "source": [
12 "source": [
13 "H1"
13 "H1"
14 ]
14 ]
15 },
15 },
16 {
16 {
17 "cell_type": "heading",
17 "cell_type": "heading",
18 "level": 2,
18 "level": 2,
19 "source": [
19 "source": [
20 "H2"
20 "H2"
21 ]
21 ]
22 },
22 },
23 {
23 {
24 "cell_type": "heading",
24 "cell_type": "heading",
25 "level": 3,
25 "level": 3,
26 "source": [
26 "source": [
27 "H3"
27 "H3"
28 ]
28 ]
29 },
29 },
30 {
30 {
31 "cell_type": "heading",
31 "cell_type": "heading",
32 "level": 4,
32 "level": 4,
33 "source": [
33 "source": [
34 "H4"
34 "H4"
35 ]
35 ]
36 },
36 },
37 {
37 {
38 "cell_type": "heading",
38 "cell_type": "heading",
39 "level": 5,
39 "level": 5,
40 "source": [
40 "source": [
41 "H5"
41 "H5"
42 ]
42 ]
43 },
43 },
44 {
44 {
45 "cell_type": "heading",
45 "cell_type": "heading",
46 "level": 6,
46 "level": 6,
47 "source": [
47 "source": [
48 "H6"
48 "H6"
49 ]
49 ]
50 },
50 },
51 {
51 {
52 "cell_type": "markdown",
52 "cell_type": "markdown",
53 "source": [
53 "source": [
54 "A section heading",
55 "=================",
56 "",
57 "A bit of text, with *important things*:",
54 "A bit of text, with *important things*:",
58 "",
55 "",
59 "* and",
56 "* and",
60 "* more",
57 "* more that **are boldface**, as well as `verbatim`.",
61 "",
58 "",
62 "Using reST links to `ipython <http://ipython.org>`_."
59 "Using markdown hyperlinks for [ipython](http://ipython.org)."
63 ]
60 ]
64 },
61 },
65 {
62 {
66 "cell_type": "code",
63 "cell_type": "code",
67 "collapsed": false,
64 "collapsed": false,
68 "input": [
65 "input": [
69 "f = figure()",
66 "f = figure()",
70 "plot([1])",
67 "plot([1,2,3])",
71 "display(f)"
68 "display(f)"
72 ],
69 ],
73 "language": "python",
70 "language": "python",
74 "outputs": [
71 "outputs": [
75 {
72 {
76 "output_type": "display_data",
73 "output_type": "display_data",
77 "png": "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\n",
74 "png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAAD3CAYAAAAJxX+sAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAG9JJREFUeJzt3Xt0VeWZx/FvEIoDA1QuEkQEEsotIZ5ATKCACZRChaK2\noMi4GBdETBXlJlXwUmCwzKy2CEUFsWMrGuINlBIQAZETMIFcJCCEwJgwmcQaMAnlZiSEZM8fr9JG\n4OR2Tva5/D5rZQmcvc5+1l7bhx/v2ed5gyzLshAREb/RzO4CRETEvdTYRUT8jBq7iIifUWMXEfEz\nauwiIn5GjV1ExM+4bOwXLlwgJiYGh8PB4MGDWb58+VWPW7BgASEhIQwaNIijR496pFAREamboNqe\nYy8vL6dVq1ZUVFQwaNAgNm7cSK9evS6/npGRwdy5c9m0aRPbtm1j3bp1bN682eOFi4jI1dW6FNOq\nVSsAzp8/z6VLl2jZsmWN19PT05k4cSLt27dn8uTJ5ObmeqZSERGpk+a1HVBdXU1kZCQ5OTmsWLGC\nbt261Xg9IyODKVOmXP59p06dyM/PJzQ0tMZxQUFBbipZRCSw1HdAQK2JvVmzZhw8eJC8vDxWrVpF\ndnb2FSf8/kmv1cS/O1Y/jftZuHCh7TX404+up66nN/188IHFLbdYTJtmcepUwya+1PmpmB49ejB2\n7FjS09Nr/HlMTAxHjhy5/PuSkhJCQkIaVIyISKAqK4N//3d45BF49VXzc8MNDXsvl429tLSU06dP\nf3vSMrZv385dd91V45iYmBg2bNhAWVkZSUlJ9OvXr2GViIgEIMuCd9+FAQOgQwc4dAhGjWrce7pc\nYy8uLuaBBx6gqqqK4OBg5s2bR5cuXVizZg0ACQkJREdHM2zYMKKiomjfvj2JiYmNq0hqFRcXZ3cJ\nfkXX0710PeuuuNgk9GPHYMMGGDLEPe9b6+OO7hIUFEQTnUpExKtZFvzlLzB/PvzqV/D00/C9Bw4v\na0jvrPWpGBERcZ/jx+Ghh+D0adixA2691f3n0EgBEZEmUFUFK1ZAdDSMGQP79nmmqYMSu4iIxx05\nAvHx8IMfQFoa9O7t2fMpsYuIeMjFi7BkCcTGwgMPwK5dnm/qoMQuIuIRWVkmpd98M+zfD9/70r5H\nKbGLiLhReTk88QSMG2f+u3lz0zZ1UGMXEXGblBTzgWhRkfmi0f33gx1jsrQUIyLSSGfPwpNPQnIy\nrFoFd95pbz1K7CIijbBlC4SHm8cZDx+2v6mDEruISIOUlsLs2bB3L7z2GowcaXdF/6DELiJSD5YF\nb71lUnrnzmYt3ZuaOiixi4jU2d/+ZoZ25efDX/8KMTF2V3R1SuwiIrWwLPjTn8DhgMhI81y6tzZ1\nUGIXEXEpPx+mT4fz5+Hjj83cdG+nxC4ichVVVfD88yaZjxtnPiT1haYOSuwiIlc4fNiMA2jVykxh\n7NXL7orqR4ldRORbFy/C4sUwYgQ8+CDs3Ol7TR2U2EVEAMjIMCm9Z084cAC6drW7ooZTYxeRgFZe\nDs8+C+vWmY0wJk2yZ76LO2kpRkQC1q5d5gPREyfMuvp99/l+UwcldhEJQGfOwK9/DVu3wurV8POf\n212Reymxi0hASU424wCaNTMp3d+aOiixi0iAKCmBmTPNzkZvvAFxcXZX5DlK7CLi1yzLfDA6YIDZ\nyejgQf9u6qDELiJ+rKgIHn4YCgvNFnVRUXZX1DSU2EXE71RXw8svw8CBZiRAVlbgNHVQYhcRP/P5\n52Zo14UL4HRCWJjdFTU9JXYR8QuXLsHvfw9DhsDdd0NqamA2dVBiFxE/8NlnZhxAu3ZmNEBIiN0V\n2UuJXUR8VkUF/OY3MGqU+ZB0xw41dVBiFxEftXevSem9e5uhXTfdZHdF3kONXUR8ytdfw9NPw9tv\nw8qVMHGif8x3cSctxYiIz/joI/NFo1OnzDiAe+5RU78aJXYR8XqnT8Pjj5vG/vLLcMcddlfk3ZTY\nRcSrbdxoHlu8/no4dEhNvS6U2EXEK508CY89Zma7vPkm3H673RX5DiV2EfEqlgWvvw4RERAaap54\nUVOvHyV2EfEahYWQkADFxfDBBzBokN0V+SYldhGxXXU1vPSSGdo1fDhkZqqpN4YSu4jY6tgxePBB\nqKqCPXugXz+7K/J9SuwiYotLl+C//guGDoV771VTdycldhFpcgcOmHEAHTqYWek9ethdkX9RYheR\nJnPhghkHMHq0eZRx2zY1dU9QYheRJpGaalJ6WJgZsxscbHdF/kuNXUQ86vx5eOopWL8eXngBJkyw\nuyL/53IppqioiBEjRhAWFkZcXBxJSUlXHON0OmnXrh2RkZFERkby3HPPeaxYEfEt27dDeDicPWuG\ndqmpNw2Xib1FixYsX74ch8NBaWkp0dHRjB8/njZt2tQ4LjY2lk2bNnm0UBHxHadOmaFdu3bBmjUw\nZozdFQUWl4k9ODgYh8MBQMeOHQkLCyMrK+uK4yzL8kx1IuJzNmwwKb1NGzO0S0296dV5jT0vL4+c\nnByio6Nr/HlQUBBpaWk4HA5GjhzJjBkzCA0NdXuhIuLdiovh0UchJwfefdc8ny72qFNjP3fuHJMm\nTWL58uW0bt26xmsDBw6kqKiIFi1asHbtWmbNmsXmzZuv+j6LFi26/Ou4uDji4uIaXLiIeAfLgrVr\n4YknYPp0WLfOjNiVhnE6nTidzka9R5BVyzpKZWUl48aNY+zYscyePdvlm1mWRXBwMIWFhbRs2bLm\niYKCtGQj4mcKCuChh6C0FP78Z/h25VbcqCG90+Uau2VZxMfHEx4efs2mfvLkycsnTU5OJiIi4oqm\nLiL+pbraPLoYFQUjR0J6upq6N3G5FJOamkpiYiIRERFERkYCsHTpUgoLCwFISEhg/fr1rF69mubN\nmxMREcGyZcs8X7WI2CY31wztatbMfOmoTx+7K5Lvq3Upxm0n0lKMiE+rrITf/x6efx4WL4aHHzbN\nXTyrIb1T3zwVkVrt3w/TpkGXLvDpp9C9u90ViSv6+1ZErumbb2D+fLOB9OOPm12N1NS9nxK7iFzV\nnj1mLf3WW83Qrs6d7a5I6kqNXURqOHfOpPSNG+HFF+EXv7C7IqkvLcWIyGVbt5pxABcumKFdauq+\nSYldRCgrgzlzzPLLq6/CqFF2VySNocQuEsAsC955x6T0Dh3M0C41dd+nxC4SoL78EmbMgGPH4L33\nYMgQuysSd1FiFwkwlmWWWxwOGDAAsrPV1P2NErtIADl+3AztOn0aduwwjzKK/1FiFwkAVVWwYgVE\nR5uNL/btU1P3Z0rsIn7uyBGIj4cf/ADS0qB3b7srEk9TYhfxUxcvwpIlEBsLDzxg9h9VUw8MSuwi\nfigz06T0bt3MAK9u3eyuSJqSEruIHykvN1vU/fzn8OSTsHmzmnogUmMX8RMpKeYD0aIi80Wj+++H\noCC7qxI7aClGxMedPWvSeXIyrFoFd95pd0ViNyV2ER+2ZYsZB1BVZYZ2qakLKLGL+KSSEpg92zyP\n/tprZkNpke8osYv4EMuCt94yowCCg80GGGrq8n1K7CI+4m9/MxtIHz8Of/0rxMTYXZF4KyV2ES9n\nWfCnP5mhXQMHmufS1dTFFSV2ES+Wnw/Tp8P58/Dxx2YJRqQ2SuwiXqiqCpYtM8l83DjYu1dNXepO\niV3Eyxw+DNOmQevW5qmXXr3srkh8jRK7iJe4eBEWLYIRI8zyy86daurSMErsIl4gI8Ok9JAQOHAA\nuna1uyLxZWrsIjYqL4dnn4V168xGGJMmab6LNJ6WYkRssmuX+UD0xAmzrn7ffWrq4h5K7CJN7PRp\nM1p361ZYvdqM2BVxJyV2kSa0aZMZ2tWsmUnpauriCUrsIk3gq69g5kzIyoLERIiLs7si8WdK7CIe\nZFnmg9EBA+CWW8zQLjV18TQldhEPKSoyQ7sKC83c9KgouyuSQKHELuJm1dXw8stmYFdMjFl+UVOX\npqTELuJGn38ODz4IFRXgdEJYmN0VSSBSYhdxg0uX4He/gyFD4Be/gNRUNXWxjxK7SCMdPAjx8fDD\nH5rRACEhdlckgU6JXaSBKirMOICf/hQeeQR27FBTF++gxC7SAHv3mpTeu7cZ2nXTTXZXJPIPauwi\n9fD11/D00/D227ByJUycqPku4n20FCNSRx99ZL5odOqUGQdwzz1q6uKdlNhFavH3v8O8eaaxv/wy\n3HGH3RWJuKbELuLC+++boV3/8i8mpaupiy9QYhe5ipMn4bHHzAejb70Fw4fbXZFI3blM7EVFRYwY\nMYKwsDDi4uJISkq66nELFiwgJCSEQYMGcfToUY8UKtIULAtefx0iIiA01DyjrqYuvibIsizrWi+e\nOHGCEydO4HA4KC0tJTo6moMHD9KmTZvLx2RkZDB37lw2bdrEtm3bWLduHZs3b77yREFBuDiViO0K\nCyEhAYqL4dVXYdAguysSaVjvdJnYg4ODcTgcAHTs2JGwsDCysrJqHJOens7EiRNp3749kydPJjc3\nt55li9iruhpeeskM7Ro+HDIz1dTFt9V5jT0vL4+cnByio6Nr/HlGRgZTpky5/PtOnTqRn59PaGio\n+6oU8ZBjx8zQrupq2LMH+vWzuyKRxqtTYz937hyTJk1i+fLltG7dusZrlmVd8c+EoGs83Lto0aLL\nv46LiyNOOw6ITSorYdky+MMfYOFCmDHDbFcnYjen04nT6WzUe7hcYweorKxk3LhxjB07ltmzZ1/x\n+gsvvMClS5eYM2cOAKGhoeTn5195Iq2xi5fIzjbjADp2hFdegR497K5I5NrcvsZuWRbx8fGEh4df\ntakDxMTEsGHDBsrKykhKSqKf/i0rXurCBTMOYMwYs//otm1q6uKfXC7FpKamkpiYSEREBJGRkQAs\nXbqUwsJCABISEoiOjmbYsGFERUXRvn17EhMTPV+1SD2lppqUHhZm9h0NDra7IhHPqXUpxm0n0lKM\n2OD8eXjqKVi/Hl54ASZMsLsikfpx+1KMiC/bts2MAzh3zowDUFOXQKGRAuJ3Tp2CuXPNnqOvvAKj\nR9tdkUjTUmIXv7Jhg0npbdualK6mLoFIiV38QnExPPoo5OTAu+/C0KF2VyRiHyV28WmWBa+9Brfe\nCn37mmmMauoS6JTYxWcVFMBDD0FpKWzfDt+ONRIJeErs4nOqqsx+o1FR8JOfQEaGmrrIP1NiF5+S\nm2uGdjVrZr501KeP3RWJeB8ldvEJlZXw29+asbr33w8pKWrqIteixC5eb/9+mDYNunSBTz+F7t3t\nrkjEuymxi9f65huYP99sIP344/DBB2rqInWhxC5eafdus5YeGWmGdnXubHdFIr5DjV28ytmzsGAB\nbNxotqu7+267KxLxPVqKEa+xdSsMGAAVFWYcgJq6SMMosYvtyspgzhz45BN49VUYNcruikR8mxK7\n2May4J13zNCuDh3g0CE1dRF3UGIXW3z5JTzyCHz+Obz3HgwZYndFIv5DiV2alGWZ5RaHAyIizDPq\nauoi7qXELk3m+HGYPh3OnIGPPjKNXUTcT4ldPK6qClasgOho+NnPYN8+NXURT1JiF4/KyYH4eGjZ\nEvbuhR/9yO6KRPyfErt4xMWLsGQJxMXB1Kmwa5eaukhTUWIXt8vMNCn9llsgOxtuvtnuikQCixK7\nuE15Ofz61zB+vBnelZyspi5iBzV2cQun0+w7+sUX5otG//ZvEBRkd1UigUlLMdIoZ87Ak0/C5s2w\nahXceafdFYmIErs02JYtZhxAdbV5+kVNXcQ7KLFLvZWUwOzZ5nn0tWth5Ei7KxKRf6bELnVmWfDm\nm2a0bpcuZi1dTV3E+yixS5188QU8/DAUFMCmTeZbpCLinZTYxaXqanjlFbNFXVSU2UxaTV3Euymx\nyzXl5ZmhXeXl5puj4eF2VyQidaHELleoqoJly2DwYPNlo7Q0NXURX6LELjUcOmTGAfzrv0J6OoSG\n2l2RiNSXErsAZgPphQvNUy4PPQQ7d6qpi/gqJXYhPd2k9JAQOHAAuna1uyIRaQw19gD29dfw7LOQ\nlAR//CPce6/mu4j4Ay3FBKiPPza7GH31FRw+DJMmqamL+Asl9gBz+rQZrbttG6xeDePG2V2RiLib\nEnsA2bTJPLbYooVJ6WrqIv5JiT0AfPUVzJxpvjW6bh3ExtpdkYh4khK7H7MsSEw0Q7u6d4fPPlNT\nFwkESux+qqgIfvUr898tW8ycFxEJDErsfqa62nwoOnAgDBkCWVlq6iKBRondj/zP/5ihXRcvQkoK\n9O9vd0UiYgcldj9w6RL87nfw4x/DL38Jn3yipi4SyFw29mnTptG5c2cGDBhw1dedTift2rUjMjKS\nyMhInnvuOY8UKdd28CDExMCOHZCZCbNmwXXX2V2ViNjJZWOfOnUqH374ocs3iI2NJTs7m+zsbJ55\n5hm3FifXVlFhxgH89KcwYwZs3w49e9pdlYh4A5dr7MOHD6egoMDlG1iW5c56pA727jVDu/r0MUO7\nbrrJ7opExJs06sPToKAg0tLScDgcjBw5khkzZhDqYtbrokWLLv86Li6OuLi4xpw+4Jw/D888A++8\nAytXwoQJmu8i4m+cTidOp7NR7xFk1RK5CwoKGD9+PIcOHbritXPnznHdddfRokUL1q5dy8aNG9m8\nefPVTxQUpHTfCDt2mDnpt98Ozz8PHTrYXZGINIWG9M5GNfZ/ZlkWwcHBFBYW0rJlS7cUJ/D3v8Pj\nj5uNL9asgZ/9zO6KRKQpNaR3Nupxx5MnT14+YXJyMhEREVdt6tIw779vhna1amWGdqmpi0hduFxj\nnzx5MikpKZSWltKtWzcWL15MZWUlAAkJCaxfv57Vq1fTvHlzIiIiWLZsWZMU7e9OnIDHHjOzXd56\nC4YPt7siEfEltS7FuO1EWoqplWXBG2+Yeenx8fCb38D119tdlYjYqSG9UyMFvMT//R8kJMDJk7B1\nq5n1IiLSEBopYLPqanjpJTOoKzYWMjLU1EWkcZTYbXTsmFlysSzYswf69rW7IhHxB0rsNqishP/8\nTxg6FO67T01dRNxLib2JZWeblN6pk5mV3qOH3RWJiL9RYm8iFy7AU0/BmDFmAuOHH6qpi4hnKLE3\ngU8+gQcfNHuPfvYZBAfbXZGI+DM1dg86dw4WLID33oMXXzSbYIiIeJqWYjxk2zaT0MvLISdHTV1E\nmo4Su5udOgVz5pg9R195BUaPtrsiEQk0SuxutH69Gdr1wx+aoV1q6iJiByV2NyguhkcfhSNHTHP/\n8Y/trkhEApkSeyNYFvzlL3DrrdCvn3lGXU1dROymxN5A//u/ZkejU6fMRtIOh90ViYgYSuz1VFVl\n9hu97TYYNQrS09XURcS7KLHXQ26uGQfQvDmkpUHv3nZXJCJyJSX2OqishN/+1mwkPWUKOJ1q6iLi\nvZTYa/HppzBtGnTtan59yy12VyQi4poS+zV88w08+SSMHWu2qtuyRU1dRHyDEvtV7N5thnZFRsKh\nQ3DjjXZXJCJSd2rs/+TsWZg/HzZtMkO77r7b7opEROpPSzHf+uADM7SrstKMA1BTFxFfFfCJvbTU\nDO1KS4M//xl+8hO7KxIRaZyATeyWBW+/bVJ6p05mAww1dRHxBwGZ2L/8Eh5+GPLy4P33YfBguysS\nEXGfgErslgX//d9maJfDAfv3q6mLiP8JmMR+/DhMn26efNm5EyIi7K5IRMQz/D6xV1XB8uUQHQ13\n3AF796qpi4h/8+vEnpNjhnZdfz3s2we9etldkYiI5/llYr94Ef7jPyAuzsx5+fhjNXURCRx+l9gz\nM00z797d7Gh08812VyQi0rT8JrGXl8O8eTB+PDz1FCQnq6mLSGDyi8budJoPRIuLzdCuyZMhKMju\nqkRE7OHTSzFnzsATT5g5L6tWmbQuIhLofDaxJydDeLhJ5ocPq6mLiHzH5xJ7SQnMmgUZGfD66zBi\nhN0ViYh4F59J7JYFSUlmaFfXrmZol5q6iMiVfCKxf/GFGdpVUGA2wYiOtrsiERHv5dWJvboa1qwx\nW9TddpvZTFpNXUTENa9N7Hl5ZmjXN9+YxxnDwuyuSETEN3hdYr90Cf7wBzNO9847ITVVTV1EpD68\nKrF/9pkZ2tW2rXnqJSTE7opERHyPVyT2igpYuNBsTZeQAB99pKYuItJQtif2fftMSu/VCw4cMI8y\niohIw9nW2L/+Gp59Ft58E/74R7jnHs13ERFxB5dLMdOmTaNz584MGDDgmscsWLCAkJAQBg0axNGj\nR+t00p07zReNSkrMOIB771VTrw+n02l3CX5F19O9dD3t57KxT506lQ8//PCar2dkZLBnzx6ysrKY\nN28e8+bNc3my06fNI4xTp8KLL8Ibb0CHDg0rPJDpfxz30vV0L11P+7ls7MOHD+eGG2645uvp6elM\nnDiR9u3bM3nyZHJzc12eLDwcWrQwKX3s2IYVLCIirjXqqZiMjAz69+9/+fedOnUiPz//mscnJZnx\num3bNuasIiLiSqM+PLUsC8uyavxZkIvF8thYLaS7y+LFi+0uwa/oerqXrqe9GtXYY2JiOHLkCGPG\njAGgpKSEkGs8gP79vwBERMQzGrUUExMTw4YNGygrKyMpKYl+/fq5qy4REWkgl4l98uTJpKSkUFpa\nSrdu3Vi8eDGVlZUAJCQkEB0dzbBhw4iKiqJ9+/YkJiY2SdEiIuKC5UYpKSlW3759rV69elkrV668\n6jHz58+3evbsaQ0cONDKzc115+n9Tm3Xc9euXVbbtm0th8NhORwOa8mSJTZU6RumTp1q3XjjjVZ4\nePg1j9G9WTe1XUvdl/VTWFhoxcXFWf3797diY2OtdevWXfW4+tyfbm3sDofDSklJsQoKCqw+ffpY\nJSUlNV5PT0+3hg4dapWVlVlJSUnWuHHj3Hl6v1Pb9dy1a5c1fvx4m6rzLbt377b2799/zWake7Pu\naruWui/rp7i42MrOzrYsy7JKSkqsnj17WmfPnq1xTH3vT7cNATtz5gwAt99+O927d2f06NGkp6fX\nOKa+z70HsrpcT9CH0nXl7u9kBLLariXovqyP4OBgHA4HAB07diQsLIysrKwax9T3/nRbY8/MzKRv\n376Xf9+/f3/27dtX45j6PvceyOpyPYOCgkhLS8PhcDB37lxdy0bQvek+ui8bLi8vj5ycHKK/t1Vc\nfe/PJh3ba9XzuXdxbeDAgRQVFZGZmUn//v2ZNWuW3SX5LN2b7qP7smHOnTvHpEmTWL58Oa1bt67x\nWn3vT7c19ttuu63GELCcnBwGDx5c45jvnnv/jqvn3gNdXa5nmzZtaNWqFS1atCA+Pp7MzEwqKiqa\nulS/oHvTfXRf1l9lZSUTJkxgypQp3HXXXVe8Xt/7022NvV27dgDs3r2bgoICduzYQUxMzBXF6bn3\nuqnL9Tx58uTlv8WTk5OJiIigZcuWTV6rP9C96T66L+vHsizi4+MJDw9n9uzZVz2mvvenW+exr1ix\ngoSEBCorK5k5cyYdO3ZkzZo1gJ57b4jaruf69etZvXo1zZs3JyIigmXLltlcsffSdzLcp7Zrqfuy\nflJTU0lMTCQiIoLIyEgAli5dSmFhIdCw+zPI0sfXIiJ+xSv2PBUREfdRYxcR8TNq7CIifkaNXUTE\nz6ixi4j4GTV2ERE/8/9mUozJaDh2nQAAAABJRU5ErkJggg==\n",
78 "text": [
75 "text": [
79 "<matplotlib.figure.Figure at 0x28f2750>"
76 "<matplotlib.figure.Figure at 0x981bccc>"
80 ]
77 ]
81 },
78 },
82 {
79 {
83 "output_type": "display_data",
80 "output_type": "display_data",
84 "png": "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\n"
81 "png": "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\n"
85 }
82 }
86 ],
83 ],
87 "prompt_number": 1
84 "prompt_number": 1
88 },
85 },
89 {
86 {
90 "cell_type": "code",
87 "cell_type": "code",
91 "collapsed": true,
88 "collapsed": true,
92 "input": [
89 "input": [
93 "# multiline input",
90 "# multiline input",
94 "x = 1",
91 "x = 1",
95 "y = 2"
92 "y = 2"
96 ],
93 ],
97 "language": "python",
94 "language": "python",
98 "outputs": [],
95 "outputs": [],
99 "prompt_number": 2
96 "prompt_number": 2
100 },
97 },
101 {
98 {
102 "cell_type": "code",
99 "cell_type": "code",
103 "collapsed": false,
100 "collapsed": false,
104 "input": [
101 "input": [
105 "1+2"
102 "1+2"
106 ],
103 ],
107 "language": "python",
104 "language": "python",
108 "outputs": [
105 "outputs": [
109 {
106 {
110 "output_type": "pyout",
107 "output_type": "pyout",
111 "prompt_number": 3,
108 "prompt_number": 3,
112 "text": [
109 "text": [
113 "3"
110 "3"
114 ]
111 ]
115 }
112 }
116 ],
113 ],
117 "prompt_number": 3
114 "prompt_number": 3
118 },
115 },
119 {
116 {
120 "cell_type": "code",
117 "cell_type": "code",
121 "collapsed": false,
118 "collapsed": false,
122 "input": [
119 "input": [
123 "print 'hello world'"
120 "print 'hello world'"
124 ],
121 ],
125 "language": "python",
122 "language": "python",
126 "outputs": [
123 "outputs": [
127 {
124 {
128 "output_type": "stream",
125 "output_type": "stream",
129 "stream": "stdout",
126 "stream": "stdout",
130 "text": [
127 "text": [
131 "hello world"
128 "hello world",
129 ""
132 ]
130 ]
133 }
131 }
134 ],
132 ],
135 "prompt_number": 4
133 "prompt_number": 4
136 },
134 },
137 {
135 {
138 "cell_type": "markdown",
136 "cell_type": "markdown",
139 "source": [
137 "source": [
140 "$e^{i\\pi} + 1 = 0$"
138 "$e^{i\\pi} + 1 = 0$"
141 ]
139 ]
142 },
140 },
143 {
141 {
144 "cell_type": "plaintext",
142 "cell_type": "raw",
145 "source": [
143 "source": [
146 "plain text"
144 "plain text"
147 ]
145 ]
148 },
146 },
149 {
147 {
150 "cell_type": "code",
148 "cell_type": "code",
151 "collapsed": true,
149 "collapsed": false,
152 "input": [],
150 "input": [
151 "import sys",
152 "m = 'A message'",
153 "print m, 'to stdout'",
154 "print >> sys.stderr, m, 'to stderr'",
155 "m"
156 ],
153 "language": "python",
157 "language": "python",
154 "outputs": []
158 "outputs": [
159 {
160 "output_type": "stream",
161 "stream": "stdout",
162 "text": [
163 "A message to stdout",
164 ""
165 ]
166 },
167 {
168 "output_type": "stream",
169 "stream": "stderr",
170 "text": [
171 "A message to stderr",
172 ""
173 ]
174 },
175 {
176 "output_type": "pyout",
177 "prompt_number": 5,
178 "text": [
179 "'A message'"
180 ]
181 }
182 ],
183 "prompt_number": 5
184 },
185 {
186 "cell_type": "code",
187 "collapsed": false,
188 "input": [
189 "# a traceback",
190 "1/0"
191 ],
192 "language": "python",
193 "outputs": [
194 {
195 "ename": "ZeroDivisionError",
196 "evalue": "integer division or modulo by zero",
197 "output_type": "pyerr",
198 "traceback": [
199 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
200 "\u001b[1;32m/home/fperez/ipython/nbconvert/tests/<ipython-input-6-03412a6702b7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# a traceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m1\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
201 "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero"
202 ]
203 }
204 ],
205 "prompt_number": 6
155 }
206 }
156 ]
207 ]
157 }
208 }
158 ]
209 ]
159 } No newline at end of file
210 }
General Comments 0
You need to be logged in to leave comments. Login now