##// END OF EJS Templates
removing unnecessary notebook, added a check in render to not reread the file if it has previously been read
removing unnecessary notebook, added a check in render to not reread the file if it has previously been read

File last commit:

r7368:da60fb14
r7370:4e0e11b5
Show More
nbconvert.py
863 lines | 26.0 KiB | text/x-python | PythonLexer
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 #!/usr/bin/env python
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 """Convert IPython notebooks to other formats, such as ReST, and HTML.
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 Example:
./nbconvert.py --format html file.ipynb
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Produces 'file.rst' and 'file.html', along with auto-generated figure files
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 called nb_figure_NN.png. To avoid the two-step process, ipynb -> rst -> html,
use '--format quick-html' which will do ipynb -> html, but won't look as
pretty.
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 """
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 #-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Fernando Perez
First working version of latex converter.
r6671 from __future__ import print_function
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 # Stdlib
Fernando Perez
Improve SVG support, other small fixes.
r6672 import codecs
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 import logging
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 import os
Fernando Perez
First working version of latex converter.
r6671 import pprint
import re
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 import subprocess
import sys
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 import json
import copy
from shutil import rmtree
Fernando Perez
First working version of latex converter.
r6671
Matthias BUSSONNIER
full inkscape path on OS X...
r6678 inkscape = 'inkscape'
if sys.platform == 'darwin':
inkscape = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
if not os.path.exists(inkscape):
inkscape = None
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 # From IPython
Paul Ivanov
use argparse from IPython
r6262 from IPython.external import argparse
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 from IPython.nbformat import current as nbformat
Paul Ivanov
remove unused import
r6257 from IPython.utils.text import indent
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 from decorators import DocInherit
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 from IPython.nbformat.v3.nbjson import BytesEncoder
from IPython.utils import py3compat
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 #-----------------------------------------------------------------------------
# Utility functions
#-----------------------------------------------------------------------------
Jonathan Taylor
DocInherit is running into recursion depth for subclasses of the original converters -- temporary overwrite
r7368 def DocInherit(f):
return f
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 def remove_fake_files_url(cell):
"""Remove from the cell source the /files/ pseudo-path we use.
"""
src = cell.source
cell.source = src.replace('/files/', '')
Fernando Perez
First working version of latex converter.
r6671 def remove_ansi(src):
"""Strip all ANSI color escape sequences from input string.
Parameters
----------
src : string
Returns
-------
string
"""
return re.sub(r'\033\[(0|\d;\d\d)m', '', src)
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677
Fernando Perez
First working version of latex converter.
r6671 # Pandoc-dependent code
def markdown2latex(src):
"""Convert a markdown string to LaTeX via pandoc.
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
First working version of latex converter.
r6671 This function will raise an error if pandoc is not installed.
Any error messages generated by pandoc are printed to stderr.
Parameters
----------
src : string
Input string, assumed to be valid markdown.
Returns
-------
out : string
Output as returned by pandoc.
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 """
Fernando Perez
First working version of latex converter.
r6671 p = subprocess.Popen('pandoc -f markdown -t latex'.split(),
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 out, err = p.communicate(src.encode('utf-8'))
Fernando Perez
First working version of latex converter.
r6671 if err:
print(err, file=sys.stderr)
#print('*'*20+'\n', out, '\n'+'*'*20) # dbg
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 return unicode(out,'utf-8')
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
Add pandoc-based markdown2rst conversion.
r7345 def markdown2rst(src):
"""Convert a markdown string to LaTeX via pandoc.
This function will raise an error if pandoc is not installed.
Any error messages generated by pandoc are printed to stderr.
Parameters
----------
src : string
Input string, assumed to be valid markdown.
Returns
-------
out : string
Output as returned by pandoc.
"""
p = subprocess.Popen('pandoc -f markdown -t rst'.split(),
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = p.communicate(src.encode('utf-8'))
if err:
print(err, file=sys.stderr)
#print('*'*20+'\n', out, '\n'+'*'*20) # dbg
return unicode(out,'utf-8')
Fernando Perez
improve rst_directive and fix bug in unknown_cell
r6222 def rst_directive(directive, text=''):
out = [directive, '']
if text:
out.extend([indent(text), ''])
return out
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 #-----------------------------------------------------------------------------
# Class declarations
#-----------------------------------------------------------------------------
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 class ConversionException(Exception):
pass
Anton I. Sipos
PEP 8 fixes.
r6253
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 class Converter(object):
default_encoding = 'utf-8'
Fernando Perez
Improve SVG support, other small fixes.
r6672 extension = str()
Fernando Perez
First working version of latex converter.
r6671 figures_counter = 0
Fernando Perez
Improve SVG support, other small fixes.
r6672 infile = str()
infile_dir = str()
infile_root = str()
files_dir = str()
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673 with_preamble = True
user_preamble = None
output = str()
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 raw_as_verbatim = False
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 def __init__(self, infile):
self.infile = infile
Fernando Perez
Improve SVG support, other small fixes.
r6672 self.infile_dir = os.path.dirname(infile)
infile_root = os.path.splitext(infile)[0]
files_dir = infile_root + '_files'
if not os.path.isdir(files_dir):
os.mkdir(files_dir)
self.infile_root = infile_root
self.files_dir = files_dir
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 self.outbase = infile_root
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239
Anton I. Sipos
PEP 8 fixes.
r6253 def dispatch(self, cell_type):
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 """return cell_type dependent render method, for example render_code
"""
Fernando Perez
First working version of latex converter.
r6671 return getattr(self, 'render_' + cell_type, self.render_unknown)
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 def convert(self, cell_separator='\n'):
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 lines = []
Paul Ivanov
new quick-html converter which has no dependencies
r6267 lines.extend(self.optional_header())
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 converted_cells = []
Fernando Perez
First working version of latex converter.
r6671 for worksheet in self.nb.worksheets:
for cell in worksheet.cells:
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 #print(cell.cell_type) # dbg
Fernando Perez
First working version of latex converter.
r6671 conv_fn = self.dispatch(cell.cell_type)
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 if cell.cell_type in ('markdown', 'raw'):
remove_fake_files_url(cell)
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 converted_cells.append('\n'.join(conv_fn(cell)))
cell_lines = cell_separator.join(converted_cells).split('\n')
lines.extend(cell_lines)
Paul Ivanov
new quick-html converter which has no dependencies
r6267 lines.extend(self.optional_footer())
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 return u'\n'.join(lines)
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239
def render(self):
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 "read, convert, and save self.infile"
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 self.read()
self.output = self.convert()
return self.save()
def read(self):
"read and parse notebook into NotebookNode called self.nb"
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 with open(self.infile) as f:
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 self.nb = nbformat.read(f, 'json')
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 def save(self, outfile=None, encoding=None):
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 "read and parse notebook into self.nb"
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 if outfile is None:
outfile = self.outbase + '.' + self.extension
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 if encoding is None:
encoding = self.default_encoding
Stefan van der Walt
Write output to current directory, instead of to source directory.
r6680 with open(outfile, 'w') as f:
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 f.write(self.output.encode(encoding))
Stefan van der Walt
Write output to current directory, instead of to source directory.
r6680 return os.path.abspath(outfile)
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
closes #7
r6279 def optional_header(self):
return []
Paul Ivanov
new quick-html converter which has no dependencies
r6267
Paul Ivanov
closes #7
r6279 def optional_footer(self):
return []
Paul Ivanov
new quick-html converter which has no dependencies
r6267
Fernando Perez
Improve SVG support, other small fixes.
r6672 def _new_figure(self, data, fmt):
"""Create a new figure file in the given format.
Returns a path relative to the input file.
"""
figname = '%s_fig_%02i.%s' % (self.infile_root,
self.figures_counter, fmt)
Fernando Perez
First working version of latex converter.
r6671 self.figures_counter += 1
Fernando Perez
Improve SVG support, other small fixes.
r6672 fullname = os.path.join(self.files_dir, figname)
# Binary files are base64-encoded, SVG is already XML
if fmt in ('png', 'jpg', 'pdf'):
data = data.decode('base64')
fopen = lambda fname: open(fname, 'wb')
else:
fopen = lambda fname: codecs.open(fname, 'wb', self.default_encoding)
with fopen(fullname) as f:
f.write(data)
return fullname
Fernando Perez
First working version of latex converter.
r6671
Anton I. Sipos
PEP 8 fixes.
r6253 def render_heading(self, cell):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """convert a heading cell
Returns list."""
Anton I. Sipos
PEP 8 fixes.
r6253 raise NotImplementedError
def render_code(self, cell):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """Convert a code cell
Returns list."""
Anton I. Sipos
PEP 8 fixes.
r6253 raise NotImplementedError
Paul Ivanov
added stream cells for stdin and stdout
r6249
Anton I. Sipos
PEP 8 fixes.
r6253 def render_markdown(self, cell):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """convert a markdown cell
Returns list."""
Anton I. Sipos
PEP 8 fixes.
r6253 raise NotImplementedError
Paul Ivanov
added stream cells for stdin and stdout
r6249
Fernando Perez
First working version of latex converter.
r6671 def render_pyout(self, output):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """convert pyout part of a code cell
Returns list."""
Anton I. Sipos
PEP 8 fixes.
r6253 raise NotImplementedError
Paul Ivanov
added stream cells for stdin and stdout
r6249
Fernando Perez
First working version of latex converter.
r6671
def render_pyerr(self, output):
"""convert pyerr part of a code cell
Returns list."""
raise NotImplementedError
Fernando Perez
Improve SVG support, other small fixes.
r6672 def _img_lines(self, img_file):
"""Return list of lines to include an image file."""
# Note: subclasses may choose to implement format-specific _FMT_lines
# methods if they so choose (FMT in {png, svg, jpg, pdf}).
raise NotImplementedError
Fernando Perez
First working version of latex converter.
r6671 def render_display_data(self, output):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """convert display data from the output of a code cell
Returns list.
"""
Fernando Perez
Improve SVG support, other small fixes.
r6672 lines = []
for fmt in ['png', 'svg', 'jpg', 'pdf']:
if fmt in output:
img_file = self._new_figure(output[fmt], fmt)
# Subclasses can have format-specific render functions (e.g.,
# latex has to auto-convert all SVG to PDF first).
lines_fun = getattr(self, '_%s_lines' % fmt, None)
if not lines_fun:
lines_fun = self._img_lines
lines.extend(lines_fun(img_file))
return lines
Paul Ivanov
added stream cells for stdin and stdout
r6249
Anton I. Sipos
PEP 8 fixes.
r6253 def render_stream(self, cell):
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 """convert stream part of a code cell
Returns list."""
raise NotImplementedError
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_raw(self, cell):
"""convert a cell with raw text
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266
Returns list."""
Anton I. Sipos
PEP 8 fixes.
r6253 raise NotImplementedError
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
First working version of latex converter.
r6671 def render_unknown(self, cell):
"""Render cells of unkown type
Returns list."""
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 data = pprint.pformat(cell)
logging.warning('Unknown cell:\n%s' % data)
return self._unknown_lines(data)
def _unknown_lines(self, data):
"""Return list of lines for an unknown cell.
Parameters
----------
data : str
The content of the unknown data as a single string.
"""
Fernando Perez
First working version of latex converter.
r6671 raise NotImplementedError
Paul Ivanov
added stream cells for stdin and stdout
r6249
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 class ConverterRST(Converter):
extension = 'rst'
Paul Ivanov
make render_heading reusable
r6264 heading_level = {1: '=', 2: '-', 3: '`', 4: '\'', 5: '.', 6: '~'}
Anton I. Sipos
PEP 8 fixes.
r6253
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Anton I. Sipos
PEP 8 fixes.
r6253 def render_heading(self, cell):
Paul Ivanov
make render_heading reusable
r6264 marker = self.heading_level[cell.level]
Anton I. Sipos
PEP 8 fixes.
r6253 return ['{0}\n{1}\n'.format(cell.source, marker * len(cell.source))]
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Anton I. Sipos
PEP 8 fixes.
r6253 def render_code(self, cell):
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 if not cell.input:
return []
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 lines = ['In[%s]:' % cell.prompt_number, '']
lines.extend(rst_directive('.. code:: python', cell.input))
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 for output in cell.outputs:
conv_fn = self.dispatch(output.output_type)
lines.extend(conv_fn(output))
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 return lines
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Anton I. Sipos
PEP 8 fixes.
r6253 def render_markdown(self, cell):
Fernando Perez
Add pandoc-based markdown2rst conversion.
r7345 #return [cell.source]
return [markdown2rst(cell.source)]
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_raw(self, cell):
if self.raw_as_verbatim:
return ['::', '', indent(cell.source), '']
else:
return [cell.source]
Anton I. Sipos
Add a plain text cell renderer.
r6256
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Anton I. Sipos
PEP 8 fixes.
r6253 def render_pyout(self, output):
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 lines = ['Out[%s]:' % output.prompt_number, '']
Paul Ivanov
added stream cells for stdin and stdout
r6249
Anton I. Sipos
Fix main() function to use new object based converters, and add a test
r6252 # output is a dictionary like object with type as a key
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 if 'latex' in output:
lines.extend(rst_directive('.. math::', output.latex))
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 if 'text' in output:
lines.extend(rst_directive('.. parsed-literal::', output.text))
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 return lines
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_pyerr(self, output):
# Note: a traceback is a *list* of frames.
return ['::', '', indent(remove_ansi('\n'.join(output.traceback))), '']
@DocInherit
Fernando Perez
Improve SVG support, other small fixes.
r6672 def _img_lines(self, img_file):
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673 return ['.. image:: %s' % img_file, '']
Fernando Perez
Improve SVG support, other small fixes.
r6672
Anton I. Sipos
Use @DocInherit to put docstrings on render dispatch functions in base class.
r6266 @DocInherit
Anton I. Sipos
PEP 8 fixes.
r6253 def render_stream(self, output):
Paul Ivanov
added stream cells for stdin and stdout
r6249 lines = []
if 'text' in output:
lines.extend(rst_directive('.. parsed-literal::', output.text))
Paul Ivanov
refactored nbconvert, nosetest pass...
r6239 return lines
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
First working version of latex converter.
r6671 @DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def _unknown_lines(self, data):
return rst_directive('.. warning:: Unknown cell') + [data]
Fernando Perez
First working version of latex converter.
r6671
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673
Paul Ivanov
new quick-html converter which has no dependencies
r6267 class ConverterQuickHTML(Converter):
extension = 'html'
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def in_tag(self, tag, src):
"""Return a list of elements bracketed by the given tag"""
return ['<%s>' % tag, src, '</%s>' % tag]
Paul Ivanov
new quick-html converter which has no dependencies
r6267 def optional_header(self):
# XXX: inject the IPython standard CSS into here
s = """<html>
<head>
</head>
<body>
"""
return s.splitlines()
def optional_footer(self):
s = """</body>
</html>
"""
return s.splitlines()
@DocInherit
def render_heading(self, cell):
marker = cell.level
return ['<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
@DocInherit
def render_code(self, cell):
if not cell.input:
return []
lines = ['<table>']
lines.append('<tr><td><tt>In [<b>%s</b>]:</tt></td><td><tt>' % cell.prompt_number)
lines.append("<br>\n".join(cell.input.splitlines()))
lines.append('</tt></td></tr>')
for output in cell.outputs:
lines.append('<tr><td></td><td>')
conv_fn = self.dispatch(output.output_type)
lines.extend(conv_fn(output))
lines.append('</td></tr>')
lines.append('</table>')
return lines
@DocInherit
def render_markdown(self, cell):
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 return self.in_tag('pre', cell.source)
Paul Ivanov
new quick-html converter which has no dependencies
r6267
@DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_raw(self, cell):
if self.raw_as_verbatim:
return self.in_tag('pre', cell.source)
else:
return [cell.source]
Paul Ivanov
new quick-html converter which has no dependencies
r6267
@DocInherit
def render_pyout(self, output):
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 lines = ['<tr><td><tt>Out[<b>%s</b>]:</tt></td></tr>' %
output.prompt_number, '<td>']
Paul Ivanov
new quick-html converter which has no dependencies
r6267
# output is a dictionary like object with type as a key
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 for out_type in ('text', 'latex'):
if out_type in output:
lines.extend(self.in_tag('pre', indent(output[out_type])))
Paul Ivanov
new quick-html converter which has no dependencies
r6267
return lines
@DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_pyerr(self, output):
# Note: a traceback is a *list* of frames.
return self.in_tag('pre', remove_ansi('\n'.join(output.traceback)))
@DocInherit
Fernando Perez
Improve SVG support, other small fixes.
r6672 def _img_lines(self, img_file):
return ['<img src="%s">' % img_file, '']
Paul Ivanov
new quick-html converter which has no dependencies
r6267
@DocInherit
def render_stream(self, output):
lines = []
if 'text' in output:
lines.append(output.text)
return lines
Anton I. Sipos
PEP 8 fixes.
r6253
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 @DocInherit
def _unknown_lines(self, data):
return ['<h2>Warning:: Unknown cell</h2>'] + self.in_tag('pre', data)
Fernando Perez
First working version of latex converter.
r6671
class ConverterLaTeX(Converter):
Fernando Perez
Improve SVG support, other small fixes.
r6672 """Converts a notebook to a .tex file suitable for pdflatex.
Note: this converter *needs*:
- `pandoc`: for all conversion of markdown cells. If your notebook only
has Raw cells, pandoc will not be needed.
- `inkscape`: if your notebook has SVG figures. These need to be
converted to PDF before inclusion in the TeX file, as LaTeX doesn't
understand SVG natively.
You will in general obtain much better final PDF results if you configure
the matplotlib backend to create SVG output with
%config InlineBackend.figure_format = 'svg'
(or set the equivalent flag at startup or in your configuration profile).
"""
Fernando Perez
First working version of latex converter.
r6671 extension = 'tex'
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673 documentclass = 'article'
documentclass_options = '11pt,english'
heading_map = {1: r'\section',
2: r'\subsection',
3: r'\subsubsection',
4: r'\paragraph',
5: r'\subparagraph',
6: r'\subparagraph'}
Fernando Perez
First working version of latex converter.
r6671
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def in_env(self, environment, lines):
Fernando Perez
First working version of latex converter.
r6671 """Return list of environment lines for input lines
Parameters
----------
env : string
Name of the environment to bracket with begin/end.
lines: """
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 out = [ur'\begin{%s}' % environment]
Fernando Perez
First working version of latex converter.
r6671 if isinstance(lines, basestring):
out.append(lines)
else: # list
out.extend(lines)
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 out.append(ur'\end{%s}' % environment)
Fernando Perez
First working version of latex converter.
r6671 return out
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673
def convert(self):
# The main body is done by the logic in the parent class, and that's
# all we need if preamble support has been turned off.
body = super(ConverterLaTeX, self).convert()
if not self.with_preamble:
return body
# But if preamble is on, then we need to construct a proper, standalone
# tex file.
# Tag the document at the top and set latex class
final = [ r'%% This file was auto-generated by IPython, do NOT edit',
r'%% Conversion from the original notebook file:',
r'%% {0}'.format(self.infile),
r'%%',
r'\documentclass[%s]{%s}' % (self.documentclass_options,
self.documentclass),
'',
]
# Load our own preamble, which is stored next to the main file. We
# need to be careful in case the script entry point is a symlink
myfile = __file__ if not os.path.islink(__file__) else \
os.readlink(__file__)
with open(os.path.join(os.path.dirname(myfile), 'preamble.tex')) as f:
final.append(f.read())
# Load any additional user-supplied preamble
if self.user_preamble:
final.extend(['', '%% Adding user preamble from file:',
'%% {0}'.format(self.user_preamble), ''])
with open(self.user_preamble) as f:
final.append(f.read())
# Include document body
final.extend([ r'\begin{document}', '',
body,
r'\end{document}', ''])
# Retun value must be a string
return '\n'.join(final)
Fernando Perez
First working version of latex converter.
r6671 @DocInherit
def render_heading(self, cell):
Fernando Perez
Add preamble support for fully self-contained output TeX files.
r6673 marker = self.heading_map[cell.level]
Fernando Perez
Fix handling of enumerations
r6675 return ['%s{%s}' % (marker, cell.source) ]
Fernando Perez
First working version of latex converter.
r6671
@DocInherit
def render_code(self, cell):
if not cell.input:
return []
# Cell codes first carry input code, we use lstlisting for that
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 lines = [ur'\begin{codecell}']
Fernando Perez
First working version of latex converter.
r6671
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 lines.extend(self.in_env('codeinput',
self.in_env('lstlisting', cell.input)))
Fernando Perez
First working version of latex converter.
r6671
outlines = []
for output in cell.outputs:
conv_fn = self.dispatch(output.output_type)
outlines.extend(conv_fn(output))
# And then output of many possible types; use a frame for all of it.
if outlines:
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 lines.extend(self.in_env('codeoutput', outlines))
Fernando Perez
First working version of latex converter.
r6671
Matthias BUSSONNIER
somme support for utf-8 in latex...
r7046 lines.append(ur'\end{codecell}')
Fernando Perez
First working version of latex converter.
r6671
return lines
Fernando Perez
Improve SVG support, other small fixes.
r6672 @DocInherit
def _img_lines(self, img_file):
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 return self.in_env('center',
Fernando Perez
Add pandoc-based markdown2rst conversion.
r7345 [r'\includegraphics[width=6in]{%s}' % img_file, r'\par'])
Fernando Perez
Improve SVG support, other small fixes.
r6672
def _svg_lines(self, img_file):
base_file = os.path.splitext(img_file)[0]
pdf_file = base_file + '.pdf'
Matthias BUSSONNIER
full inkscape path on OS X...
r6678 subprocess.check_call([ inkscape, '--export-pdf=%s' % pdf_file,
Fernando Perez
Improve SVG support, other small fixes.
r6672 img_file])
return self._img_lines(pdf_file)
Fernando Perez
First working version of latex converter.
r6671
@DocInherit
def render_stream(self, output):
lines = []
if 'text' in output:
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 lines.extend(self.in_env('verbatim', output.text.strip()))
Fernando Perez
First working version of latex converter.
r6671
return lines
@DocInherit
def render_markdown(self, cell):
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 return [markdown2latex(cell.source)]
Fernando Perez
First working version of latex converter.
r6671
@DocInherit
def render_pyout(self, output):
lines = []
# output is a dictionary like object with type as a key
if 'latex' in output:
lines.extend(output.latex)
if 'text' in output:
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 lines.extend(self.in_env('verbatim', output.text))
Fernando Perez
First working version of latex converter.
r6671
return lines
@DocInherit
def render_pyerr(self, output):
# Note: a traceback is a *list* of frames.
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 return self.in_env('traceback',
self.in_env('verbatim',
Fernando Perez
First working version of latex converter.
r6671 remove_ansi('\n'.join(output.traceback))))
@DocInherit
Fernando Perez
Fix handling of raw cells in all converters, add stderr to test nb
r6674 def render_raw(self, cell):
if self.raw_as_verbatim:
return self.in_env('verbatim', cell.source)
else:
return [cell.source]
@DocInherit
def _unknown_lines(self, data):
return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \
self.in_env('verbatim', data)
Fernando Perez
First working version of latex converter.
r6671
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366
class ConverterNotebook(Converter):
"""
A converter that is essentially a null-op.
This exists so it can be subclassed
for custom handlers of .ipynb files
that create new .ipynb files.
What distinguishes this from JSONWriter is that
subclasses can specify what to do with each type of cell.
Writes out a notebook file.
"""
extension = 'ipynb'
def __init__(self, infile, outbase):
Converter.__init__(self, infile)
self.outbase = outbase
rmtree(self.files_dir)
def convert(self):
return json.dumps(json.loads(Converter.convert(self, ',')), indent=1, sort_keys=True)
def optional_header(self):
s = \
"""{
"metadata": {
"name": "%(name)s"
},
"nbformat": 3,
"worksheets": [
{
"cells": [""" % {'name':self.outbase}
return s.split('\n')
def optional_footer(self):
s = \
"""]
}
]
}"""
return s.split('\n')
@DocInherit
def render_heading(self, cell):
return cell_to_lines(cell)
@DocInherit
def render_code(self, cell):
return cell_to_lines(cell)
@DocInherit
def render_markdown(self, cell):
return cell_to_lines(cell)
@DocInherit
def render_raw(self, cell):
return cell_to_lines(cell)
@DocInherit
def render_pyout(self, output):
return cell_to_lines(cell)
@DocInherit
def render_pyerr(self, output):
return cell_to_lines(cell)
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 #-----------------------------------------------------------------------------
# Standalone conversion functions
#-----------------------------------------------------------------------------
Fernando Perez
First working version of latex converter.
r6671
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 def rst2simplehtml(infile):
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 """Convert a rst file to simplified html suitable for blogger.
This just runs rst2html with certain parameters to produce really simple
html and strips the document header, so the resulting file can be easily
pasted into a blogger edit window.
"""
# This is the template for the rst2html call that produces the cleanest,
# simplest html I could find. This should help in making it easier to
# paste into the blogspot html window, though I'm still having problems
# with linebreaks there...
smithj1
Reverted call to "rst2html.py" to "rst2html".
r6229 cmd_template = ("rst2html --link-stylesheet --no-xml-declaration "
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 "--no-generator --no-datestamp --no-source-link "
"--no-toc-backlinks --no-section-numbering "
"--strip-comments ")
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 cmd = "%s %s" % (cmd_template, infile)
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
html, stderr = proc.communicate()
if stderr:
raise IOError(stderr)
# Make an iterator so breaking out holds state. Our implementation of
# searching for the html body below is basically a trivial little state
# machine, so we need this.
walker = iter(html.splitlines())
# Find start of main text, break out to then print until we find end /div.
# This may only work if there's a real title defined so we get a 'div class'
# tag, I haven't really tried.
for line in walker:
smithj1
Added heading cell converter. Also changed the down-parser for output to html (from looking for <div> and </div> to <body> and </body>.
r6228 if line.startswith('<body>'):
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 break
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 newfname = os.path.splitext(infile)[0] + '.html'
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 with open(newfname, 'w') as f:
for line in walker:
smithj1
Added heading cell converter. Also changed the down-parser for output to html (from looking for <div> and </div> to <body> and </body>.
r6228 if line.startswith('</body>'):
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 break
f.write(line)
f.write('\n')
Anton I. Sipos
PEP 8 fixes.
r6253
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 return newfname
Jonathan Taylor
overriding DocInherit due to recursion depth errors
r7366 #-----------------------------------------------------------------------------
# Cell-level functions -- similar to IPython.nbformat.v3.rwbase functions
# but at cell level instead of whole notebook level
#-----------------------------------------------------------------------------
def writes_cell(cell, **kwargs):
kwargs['cls'] = BytesEncoder
kwargs['indent'] = 3
kwargs['sort_keys'] = True
kwargs['separators'] = (',',': ')
if kwargs.pop('split_lines', True):
cell = split_lines_cell(copy.deepcopy(cell))
return py3compat.str_to_unicode(json.dumps(cell, **kwargs), 'utf-8')
_multiline_outputs = ['text', 'html', 'svg', 'latex', 'javascript', 'json']
def split_lines_cell(cell):
"""
Split lines within a cell as in
IPython.nbformat.v3.rwbase.split_lines
"""
if cell.cell_type == 'code':
if 'input' in cell and isinstance(cell.input, basestring):
cell.input = (cell.input + '\n').splitlines()
for output in cell.outputs:
for key in _multiline_outputs:
item = output.get(key, None)
if isinstance(item, basestring):
output[key] = (item + '\n').splitlines()
else: # text, heading cell
for key in ['source', 'rendered']:
item = cell.get(key, None)
if isinstance(item, basestring):
cell[key] = (item + '\n').splitlines()
return cell
def cell_to_lines(cell):
'''
Write a cell to json, returning the split lines.
'''
split_lines_cell(cell)
s = writes_cell(cell).strip()
return s.split('\n')
Fernando Perez
First working version of latex converter.
r6671 known_formats = "rst (default), html, quick-html, latex"
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 def main(infile, format='rst'):
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220 """Convert a notebook to html in one step"""
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 # XXX: this is just quick and dirty for now. When adding a new format,
# make sure to add it to the `known_formats` string above, which gets
# printed in in the catch-all else, as well as in the help
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 if format == 'rst':
converter = ConverterRST(infile)
converter.render()
elif format == 'html':
#Currently, conversion to html is a 2 step process, nb->rst->html
converter = ConverterRST(infile)
rstfname = converter.render()
rst2simplehtml(rstfname)
Paul Ivanov
new quick-html converter which has no dependencies
r6267 elif format == 'quick-html':
converter = ConverterQuickHTML(infile)
rstfname = converter.render()
Fernando Perez
First working version of latex converter.
r6671 elif format == 'latex':
converter = ConverterLaTeX(infile)
latexfname = converter.render()
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 else:
raise SystemExit("Unknown format '%s', " % format +
"known formats are: " + known_formats)
Fernando Perez
Initial checkin - note that in this state, it's producing an ipython...
r6220
Fernando Perez
Fix handling of local files with the /files/ pseudo-url.
r6677 #-----------------------------------------------------------------------------
# Script main
#-----------------------------------------------------------------------------
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawTextHelpFormatter)
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 # TODO: consider passing file like object around, rather than filenames
# would allow us to process stdin, or even http streams
#parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
#Require a filename as a positional argument
parser.add_argument('infile', nargs=1)
Anton I. Sipos
Add help for format command line option.
r6265 parser.add_argument('-f', '--format', default='rst',
Paul Ivanov
list known formats in help & on unknown fmt error...
r6280 help='Output format. Supported formats: \n' +
known_formats)
Anton I. Sipos
Add argument parsing, and ability to convert an HTML file from command line
r6261 args = parser.parse_args()
main(infile=args.infile[0], format=args.format)