##// END OF EJS Templates
some improvement
some improvement

File last commit:

r9218:3d234d0c
r9218:3d234d0c
Show More
template.py
289 lines | 8.5 KiB | text/x-python | PythonLexer
Matthias BUSSONNIER
starting templates
r8994 """Base classes for the notebook conversion pipeline.
This module defines Converter, from which all objects designed to implement
a conversion of IPython notebooks to some other format should inherit.
"""
#-----------------------------------------------------------------------------
# Copyright (c) 2012, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import print_function, absolute_import
# Stdlib imports
import io
import os
Matthias BUSSONNIER
multiple env
r9212 import re
Matthias BUSSONNIER
read css from ipython dir
r9040 from IPython.utils import path
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
remove and clean code
r9183 from jinja2 import Environment, FileSystemLoader
Matthias BUSSONNIER
try to play with data display priority
r9049 env = Environment(
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184 loader=FileSystemLoader('./templates/'),
Matthias BUSSONNIER
try to play with data display priority
r9049 extensions=['jinja2.ext.loopcontrols']
)
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
multiple env
r9212 texenv = Environment(
loader=FileSystemLoader('./templates/tex/'),
extensions=['jinja2.ext.loopcontrols']
)
Matthias BUSSONNIER
starting templates
r8994 # IPython imports
from IPython.nbformat import current as nbformat
Matthias BUSSONNIER
remove and clean code
r9183 from IPython.config.configurable import Configurable
Matthias BUSSONNIER
lots of modification for latex
r9214 from IPython.utils.traitlets import ( Unicode, Any, List)
Matthias BUSSONNIER
starting templates
r8994
# Our own imports
from IPython.utils.text import indent
from .utils import remove_ansi
Matthias BUSSONNIER
null template
r8997 from markdown import markdown
Matthias BUSSONNIER
remove and clean code
r9183 from .utils import highlight, ansi2html
Matthias BUSSONNIER
start tex template
r9213 from .utils import markdown2latex
Matthias BUSSONNIER
starting templates
r8994 #-----------------------------------------------------------------------------
# Class declarations
#-----------------------------------------------------------------------------
def rm_fake(strng):
return strng.replace('/files/', '')
class ConversionException(Exception):
pass
def python_comment(string):
return '# '+'\n# '.join(string.split('\n'))
Matthias BUSSONNIER
read css from ipython dir
r9040
def header_body():
Matthias BUSSONNIER
remove and clean code
r9183 """Return the body of the header as a list of strings."""
from pygments.formatters import HtmlFormatter
header = []
static = os.path.join(path.get_ipython_package_dir(),
'frontend', 'html', 'notebook', 'static',
)
here = os.path.split(os.path.realpath(__file__))[0]
css = os.path.join(static, 'css')
for sheet in [
# do we need jquery and prettify?
# os.path.join(static, 'jquery', 'css', 'themes', 'base',
# 'jquery-ui.min.css'),
# os.path.join(static, 'prettify', 'prettify.css'),
os.path.join(css, 'boilerplate.css'),
os.path.join(css, 'fbm.css'),
os.path.join(css, 'notebook.css'),
os.path.join(css, 'renderedhtml.css'),
# our overrides:
os.path.join(here, '..', 'css', 'static_html.css'),
]:
with io.open(sheet, encoding='utf-8') as f:
s = f.read()
header.append(s)
pygments_css = HtmlFormatter().get_style_defs('.highlight')
header.append(pygments_css)
return header
Matthias BUSSONNIER
some improvement
r9218 # todo, make the key part configurable.
Matthias BUSSONNIER
test_file extractor
r9217 def _new_figure(data, fmt, count):
"""Create a new figure file in the given format.
Returns a path relative to the input file.
"""
figname = '_fig_%02i.%s' % (count, fmt)
# Binary files are base64-encoded, SVG is already XML
if fmt in ('png', 'jpg', 'pdf'):
data = data.decode('base64')
return figname,data
Matthias BUSSONNIER
remove and clean code
r9183 inlining = {}
Matthias BUSSONNIER
modularize inlining
r9048 inlining['css'] = header_body()
Matthias BUSSONNIER
read css from ipython dir
r9040
Matthias BUSSONNIER
try to play with data display priority
r9049
Matthias BUSSONNIER
lots of modification for latex
r9214
Matthias BUSSONNIER
starting templates
r8994 env.filters['pycomment'] = python_comment
env.filters['indent'] = indent
env.filters['rm_fake'] = rm_fake
env.filters['rm_ansi'] = remove_ansi
Matthias BUSSONNIER
null template
r8997 env.filters['markdown'] = markdown
env.filters['highlight'] = highlight
Matthias BUSSONNIER
svgoutput
r9039 env.filters['ansi2html'] = ansi2html
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185
Matthias BUSSONNIER
multiple env
r9212
LATEX_SUBS = (
(re.compile(r'\\'), r'\\textbackslash'),
(re.compile(r'([{}_#%&$])'), r'\\\1'),
(re.compile(r'~'), r'\~{}'),
(re.compile(r'\^'), r'\^{}'),
(re.compile(r'"'), r"''"),
(re.compile(r'\.\.\.+'), r'\\ldots'),
)
def escape_tex(value):
newval = value
for pattern, replacement in LATEX_SUBS:
newval = pattern.sub(replacement, newval)
return newval
texenv.block_start_string = '((*'
texenv.block_end_string = '*))'
texenv.variable_start_string = '((('
texenv.variable_end_string = ')))'
texenv.comment_start_string = '((='
texenv.comment_end_string = '=))'
texenv.filters['escape_tex'] = escape_tex
texenv.filters['pycomment'] = python_comment
texenv.filters['indent'] = indent
texenv.filters['rm_fake'] = rm_fake
texenv.filters['rm_ansi'] = remove_ansi
texenv.filters['markdown'] = markdown
texenv.filters['highlight'] = highlight
texenv.filters['ansi2html'] = ansi2html
Matthias BUSSONNIER
start tex template
r9213 texenv.filters['markdown2latex'] = markdown2latex
Matthias BUSSONNIER
test_file extractor
r9217
Matthias BUSSONNIER
some improvement
r9218 def cell_preprocessor(function):
""" wrap a function to be executed on all cells of a notebook
wrapped function parameters :
cell : the cell
other : external resources
index : index of the cell
"""
def wrappedfunc(nb,other):
for worksheet in nb.worksheets :
for index, cell in enumerate(worksheet.cells):
worksheet.cells[index],other= function(cell,other,index)
return nb,other
return wrappedfunc
@cell_preprocessor
def haspyout_transformer(cell, other, count):
"""
Add a haspyout flag to cell that have it
Easier for templating, where you can't know in advance
wether to write the out prompt
Matthias BUSSONNIER
test_file extractor
r9217
Matthias BUSSONNIER
some improvement
r9218 """
cell.type = cell.cell_type
cell.haspyout = False
for out in cell.get('outputs', []):
if out.output_type == 'pyout':
cell.haspyout = True
break
return cell,other
@cell_preprocessor
def outline_figure_transformer(cell,other,count):
for i,out in enumerate(cell.get('outputs', [])):
for type in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg']:
if out.hasattr(type):
figname,data = _new_figure(out[type], type,count)
cell.outputs[i][type] = figname
out['key_'+type] = figname
other[figname] = data
count = count+1
Matthias BUSSONNIER
test_file extractor
r9217 return nb,other
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185
Matthias BUSSONNIER
some improvement
r9218
Matthias BUSSONNIER
starting templates
r8994 class ConverterTemplate(Configurable):
Matthias BUSSONNIER
add docstring
r9209 """ A Jinja2 base converter templates"""
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
lots of modification for latex
r9214 display_data_priority = List(['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text'],
config=True,
help= """
A list of ast.NodeTransformer subclass instances, which will be applied
to user input before code is run.
"""
)
Matthias BUSSONNIER
some improvement
r9218
extract_figures = Bool(False,
config=True,
help= """
wether to remove figure data from ipynb and store them in auxiliary
dictionnary
"""
)
Matthias BUSSONNIER
starting templates
r8994 #-------------------------------------------------------------------------
# Instance-level attributes that are set in the constructor for this
# class.
#-------------------------------------------------------------------------
infile = Any()
Matthias BUSSONNIER
deal with worksheets
r9010
Matthias BUSSONNIER
starting templates
r8994 infile_dir = Unicode()
Matthias BUSSONNIER
lots of modification for latex
r9214
def filter_data_type(self,output):
for fmt in self.display_data_priority:
if fmt in output:
return [fmt]
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
multiple env
r9212 def __init__(self, tplfile='fullhtml', preprocessors=[], config=None,tex_environement=False, **kw):
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184 """
Matthias BUSSONNIER
add docstring
r9209 tplfile : jinja template file to process.
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184
Matthias BUSSONNIER
add docstring
r9209 config: the Configurable confg object to pass around
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184
Matthias BUSSONNIER
add docstring
r9209 preprocessors: list of function to run on ipynb json data before conversion
to extract/inline file,
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184
"""
Matthias BUSSONNIER
multiple env
r9212 self.env = texenv if tex_environement else env
Matthias BUSSONNIER
some improvement
r9218 self.ext = '.tplx' if tex_environement else '.tpl'
Matthias BUSSONNIER
remove and clean code
r9183 self.nb = None
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184 self.preprocessors = preprocessors
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185 self.preprocessors.append(haspyout_transformer)
Matthias BUSSONNIER
test_file extractor
r9217 self.preprocessors.append(outline_figure_transformer)
Matthias BUSSONNIER
remove and clean code
r9183 super(ConverterTemplate, self).__init__(config=config, **kw)
Matthias BUSSONNIER
lots of modification for latex
r9214 self.env.filters['filter_data_type'] = self.filter_data_type
self.template = self.env.get_template(tplfile+self.ext)
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185
Matthias BUSSONNIER
starting templates
r8994 def process(self):
Matthias BUSSONNIER
add docstring
r9209 """
Matthias BUSSONNIER
some improvement
r9218 preprocess the notebook json for easier use with the templates.
will call all the `preprocessor`s in order before returning it.
Matthias BUSSONNIER
add docstring
r9209 """
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184 nb = self.nb
for preprocessor in self.preprocessors:
Matthias BUSSONNIER
test_file extractor
r9217 nb,others = preprocessor(nb,{})
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9184
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185 return nb
Matthias BUSSONNIER
starting templates
r8994
Matthias BUSSONNIER
remove and clean code
r9183 def convert(self):
Matthias BUSSONNIER
Start to think on api...
r9182 """ convert the ipynb file
return both the converted ipynb file and a dict containing potential
other resources
"""
Matthias BUSSONNIER
preprocessing and namespace fix...
r9185 return self.template.render(nb=self.process(), inlining=inlining), {}
Matthias BUSSONNIER
starting templates
r8994
def read(self, filename):
"read and parse notebook into NotebookNode called self.nb"
Matthias BUSSONNIER
fix utf8
r9014 with io.open(filename) as f:
Matthias BUSSONNIER
starting templates
r8994 self.nb = nbformat.read(f, 'json')