##// END OF EJS Templates
Post code-review, extended refactor.
Post code-review, extended refactor.

File last commit:

r10485:1de3574b
r10485:1de3574b
Show More
base.py
266 lines | 9.9 KiB | text/x-python | PythonLexer
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 """Exporter for the notebook conversion pipeline.
Matthias BUSSONNIER
starting templates
r9578
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 This module defines Exporter, a highly configurable converter
that uses Jinja2 to export notebook files into different format.
Matthias BUSSONNIER
document
r9665
You can register both pre-transformers that will act on the notebook format
befor conversion and jinja filter that would then be availlable in the templates
Matthias BUSSONNIER
starting templates
r9578 """
Matthias BUSSONNIER
fix some relative path issues
r9819
Matthias BUSSONNIER
starting templates
r9578 #-----------------------------------------------------------------------------
Matthias BUSSONNIER
document
r9665 # Copyright (c) 2013, the IPython Development Team.
Matthias BUSSONNIER
starting templates
r9578 #
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 from __future__ import print_function, absolute_import
Matthias BUSSONNIER
document
r9665
# Stdlib imports
import io
Matthias BUSSONNIER
fix some relative path issues
r9819 import os
Matthias BUSSONNIER
document
r9665
# IPython imports
from IPython.config.configurable import Configurable
from IPython.nbformat import current as nbformat
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 from IPython.utils.text import indent
Matthias BUSSONNIER
do a markdown converter
r9701
Matthias BUSSONNIER
document
r9665 # other libs/dependencies
from jinja2 import Environment, FileSystemLoader
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 from markdown import markdown
Matthias BUSSONNIER
document
r9665
Jonathan Frederic
Post code-review, extended refactor.
r10485 # local import
import filters.strings
import filters.markdown
import filters.latex
import filters.datatypefilter
import filters.pygments
import filters.ansi
import transformers.extractfigure
import transformers.csshtmlheader
import transformers.revealhelp
import transformers.coalescestreams
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
Matthias BUSSONNIER
document
r9665
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #Standard Jinja2 environment constants
TEMPLATE_PATH = "/../templates/"
TEMPLATE_SKELETON_PATH = "/../templates/skeleton/"
TEMPLATE_EXTENSION = ".tpl"
Matthias BUSSONNIER
move transformer in separate file
r9621
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #Jinja2 extensions to load.
JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
#-----------------------------------------------------------------------------
# Classes and functions
Matthias BUSSONNIER
document
r9665 #-----------------------------------------------------------------------------
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 class Exporter(Configurable):
Matthias BUSSONNIER
stateless converter
r9640 """ A Jinja2 base converter templates
Jonathan Frederic
Post code-review, extended refactor.
r10485 Pre-process the IPYNB files, feed it through Jinja2 templates,
Matthias BUSSONNIER
stateless converter
r9640 and spit an converted files and a data object with other data
Jonathan Frederic
Fixed typo
r9771 should be mostly configurable
Matthias BUSSONNIER
stateless converter
r9640 """
Matthias BUSSONNIER
starting templates
r9578
Matthias BUSSONNIER
stateless converter
r9640 pre_transformer_order = List(['haspyout_transformer'],
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 config=True,
help= """
Jonathan Frederic
Post code-review, extended refactor.
r10485 An ordered list of pre-transformer to apply to the IPYNB
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 file before running through templates
"""
)
Matthias BUSSONNIER
use configuration file to do nice stuff
r9618
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 template_file = Unicode(
'', config=True,
help="Name of the template file to use")
Jonathan Frederic
Added datetime access to Jinja
r9768
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 fileext = Unicode(
'txt', config=True,
help="Extension of the file that should be written to disk"
)
stdout = Bool(
True, config=True,
Jonathan Frederic
Post code-review, extended refactor.
r10485 help="""Whether to print the converted IPYNB file to stdout
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 "use full do diff files without actually writing a new file"""
)
write = Bool(
False, config=True,
help="""Should the converted notebook file be written to disk
along with potential extracted resources."""
)
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #Processors that process the input data prior to the export, set in the
#constructor for this class.
preprocessors = []
Matthias BUSSONNIER
stateless converter
r9640
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 def __init__(self, preprocessors={}, jinja_filters={}, config=None, export_format, **kw):
Jonathan Frederic
Fixed some weird things that happened after my first...
r9769 """ Init a new converter.
config: the Configurable config object to pass around.
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9603
Matthias BUSSONNIER
allow configurable filters
r9650 preprocessors: dict of **availlable** key/value function to run on
Matthias BUSSONNIER
document
r9665 ipynb json data before conversion to extract/inline file.
See `transformer.py` and `ConfigurableTransformers`
Matthias BUSSONNIER
allow configurable filters
r9650
Matthias BUSSONNIER
document
r9665 set the order in which the transformers should apply
with the `pre_transformer_order` trait of this class
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9603
Matthias BUSSONNIER
document
r9665 transformers registerd by this key will take precedence on
default one.
jinja_filters: dict of supplementary jinja filter that should be made
availlable in template. If those are of Configurable Class type,
they will be instanciated with the config object as argument.
user defined filter will overwrite the one availlable by default.
Matthias BUSSONNIER
add possibility to preprocess ipynb files
r9603 """
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435
Jonathan Frederic
Post code-review, extended refactor.
r10485 #Set the default options for the exporter.
default_config = self.config
#Set properties that must be set in the config class in order to
#propagate to other classes.
default_config.GlobalConfigurable.display_data_priority =['svg', 'png', 'latex', 'jpg', 'jpeg','text']
default_config.ExtractFigureTransformer.display_data_priority=['svg', 'png', 'latex', 'jpg', 'jpeg','text']
#Set default properties of the exporter.
#For most (or all cases), the template file name matches the format name.
self.display_data_priority= ['svg', 'png', 'latex', 'jpg', 'jpeg','text']
self.template_file = export_format
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 if not config == None:
default_config._merge(config)
Jonathan Frederic
Post code-review, extended refactor.
r10485 config = default_config
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 #Call the base class constructor
super(Exporter, self).__init__(config=config, **kw)
Matthias BUSSONNIER
document
r9665
Jonathan Frederic
Moved latex code into latex exporter
r10480 #Standard environment
self.ext = TEMPLATE_EXTENSION
Jonathan Frederic
Post code-review, extended refactor.
r10485 self._init_environment()
Matthias BUSSONNIER
create configurable preprocessors
r9624
Jonathan Frederic
Post code-review, extended refactor.
r10485 #TODO: Implement reflection style methods to get user transformers.
#for name in self.pre_transformer_order:
# # get the user-defined transformer first
# transformer = preprocessors.get(name, getattr(trans, name, None))
# if isinstance(transformer, MetaHasTraits):
# transformer = transformer(config=config)
# self.preprocessors.append(transformer)
Matthias BUSSONNIER
stateless converter
r9640
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #For compatibility, TODO: remove later.
Jonathan Frederic
Post code-review, extended refactor.
r10485 self.preprocessors.append(transformers.coalescestreams.coalesce_streams)
self.preprocessors.append(transformers.extractfigure.ExtractFigureTransformer(config=config))
self.preprocessors.append(transformers.revealhelp.RevealHelpTransformer(config=config))
self.preprocessors.append(transformers.csshtmlheader.CSSHtmlHeaderTransformer(config=config))
Matthias BUSSONNIER
flag for extracting figure
r9615
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #Add filters to the Jinja2 environment
Jonathan Frederic
Post code-review, extended refactor.
r10485 self._register_filters(config)
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431
#Load user filters. Overwrite existing filters if need be.
for key, user_filter in jinja_filters.iteritems():
if isinstance(user_filter, MetaHasTraits):
self.env.filters[key] = user_filter(config=config)
else:
self.env.filters[key] = user_filter
#Load the template file.
Matthias BUSSONNIER
use configuration file to do nice stuff
r9618 self.template = self.env.get_template(self.template_file+self.ext)
Matthias BUSSONNIER
lots of modification for latex
r9611
Matthias BUSSONNIER
starting templates
r9578
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 def export(self, nb):
"""Export notebook object
nb: Notebook object to export.
Returns both the converted ipynb file and a dict containing the
resources created along the way via the transformers and Jinja2
processing.
Matthias BUSSONNIER
Start to think on api...
r9601 """
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431
nb, resources = self._preprocess(nb)
Matthias BUSSONNIER
move html header out
r9654 return self.template.render(nb=nb, resources=resources), resources
Matthias BUSSONNIER
starting templates
r9578
Matthias BUSSONNIER
stateless converter
r9640 def from_filename(self, filename):
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 """Read and export a notebook from a filename
Matthias BUSSONNIER
create configurable preprocessors
r9624
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 filename: Filename of the notebook file to export.
Matthias BUSSONNIER
allow configurable filters
r9650
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 Returns both the converted ipynb file and a dict containing the
resources created along the way via the transformers and Jinja2
processing.
Matthias BUSSONNIER
more doc and future API
r9666 """
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 with io.open(filename) as f:
return self.export(nbformat.read(f, 'json'))
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 def from_file(self, file_stream):
"""Read and export a notebook from a filename
Matthias BUSSONNIER
more doc and future API
r9666
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 file_stream: File handle of file that contains notebook data.
Matthias BUSSONNIER
more doc and future API
r9666
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 Returns both the converted ipynb file and a dict containing the
resources created along the way via the transformers and Jinja2
processing.
Matthias BUSSONNIER
more doc and future API
r9666 """
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 return self.export(nbformat.read(file_stream, 'json'))
Jonathan Frederic
Post code-review, extended refactor.
r10485 def _init_environment(self):
self.env = Environment(
loader=FileSystemLoader([
os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_PATH,
os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_SKELETON_PATH,
]),
extensions=JINJA_EXTENSIONS
)
def _register_filters(self, config):
self.env.filters['indent'] = indent
self.env.filters['markdown'] = markdown
self.env.filters['ansi2html'] = filters.ansi.ansi2html
self.env.filters['filter_data_type'] = filters.datatypefilter.DataTypeFilter(config=config)
self.env.filters['get_lines'] = filters.strings.get_lines
self.env.filters['highlight'] = filters.pygments.highlight
self.env.filters['highlight2html'] = filters.pygments.highlight
self.env.filters['highlight2latex'] = filters.pygments.highlight2latex
self.env.filters['markdown2latex'] = filters.markdown.markdown2latex
self.env.filters['markdown2rst'] = filters.markdown.markdown2rst
self.env.filters['pycomment'] = filters.strings.python_comment
self.env.filters['rm_ansi'] = filters.ansi.remove_ansi
self.env.filters['rm_dollars'] = filters.strings.strip_dollars
self.env.filters['rm_fake'] = filters.strings.rm_fake
self.env.filters['rm_math_space'] = filters.latex.rm_math_space
self.env.filters['wrap'] = filters.strings.wrap
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 def _preprocess(self, nb):
""" Preprocess the notebook using the transformers specific
for the current export format.
nb: Notebook to preprocess
"""
#Dict of 'resources' that can be filled by the preprocessors.
resources = {}
#Run each transformer on the notebook. Carry the output along
#to each transformer
for transformer in self.preprocessors:
nb, resources = transformer(nb, resources)
return nb, resources