##// END OF EJS Templates
add markdown2html filter...
add markdown2html filter uses pandoc instead of Python markdown for better consistency. Also eliminates one dependency.

File last commit:

r11268:fa5d4c0a
r11268:fa5d4c0a
Show More
exporter.py
337 lines | 11.5 KiB | text/x-python | PythonLexer
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """This module defines Exporter, a highly configurable converter
that uses Jinja2 to export notebook files into different formats.
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
Cleanup and refactor of API, almost complete....
r10677
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
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 import inspect
Matthias BUSSONNIER
start tinkerign with config system
r10862 from copy import deepcopy
Matthias BUSSONNIER
document
r9665
Brian E. Granger
Fixing import for nbconvert.
r11089 # other libs/dependencies
from jinja2 import Environment, FileSystemLoader
Matthias BUSSONNIER
document
r9665 # IPython imports
from IPython.config.configurable import Configurable
Matthias BUSSONNIER
start tinkerign with config system
r10862 from IPython.config import Config
Matthias BUSSONNIER
document
r9665 from IPython.nbformat import current as nbformat
Brian E. Granger
Fixing import for nbconvert.
r11089 from IPython.utils.traitlets import MetaHasTraits, Unicode
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
Brian E. Granger
Fixing import for nbconvert.
r11089 from IPython.nbconvert import filters
from IPython.nbconvert import transformers
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 #Jinja2 extensions to load.
JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
Matthias BUSSONNIER
fix filters documentation....
r10838 default_filters = {
'indent': indent,
MinRK
add markdown2html filter...
r11268 'markdown': filters.markdown2html,
Brian E. Granger
Fixing import for nbconvert.
r11089 'ansi2html': filters.ansi2html,
'filter_data_type': filters.DataTypeFilter,
'get_lines': filters.get_lines,
'highlight': filters.highlight,
'highlight2html': filters.highlight,
'highlight2latex': filters.highlight2latex,
'markdown2latex': filters.markdown2latex,
'markdown2rst': filters.markdown2rst,
'pycomment': filters.python_comment,
'rm_ansi': filters.remove_ansi,
'rm_dollars': filters.strip_dollars,
'rm_fake': filters.rm_fake,
'ansi2latex': filters.ansi2latex,
'rm_math_space': filters.rm_math_space,
'wrap': filters.wrap
Matthias BUSSONNIER
fix filters documentation....
r10838 }
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #-----------------------------------------------------------------------------
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677 # Class
Matthias BUSSONNIER
document
r9665 #-----------------------------------------------------------------------------
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677
Jonathan Frederic
Refactoring for the rename of ConverterTemplate to Exporter.
r10430 class Exporter(Configurable):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Exports notebooks into other file formats. Uses Jinja 2 templating engine
to output new formats. Inherit from this class if you are creating a new
template type along with new filters/transformers. If the filters/
transformers provided by default suffice, there is no need to inherit from
this class. Instead, override the template_file and file_extension
traits via a config file.
Matthias BUSSONNIER
fix filters documentation....
r10838 {filters}
"""
Matthias BUSSONNIER
finish up config merging
r10874
# finish the docstring
Matthias BUSSONNIER
fix filters documentation....
r10838 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
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
Added latexexporter
r10587 file_extension = Unicode(
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 'txt', config=True,
help="Extension of the file that should be written to disk"
)
Jonathan Frederic
Finished rename/refact on API namespace
r10690 template_path = Unicode(
MinRK
Don't hardcode posix paths in nbconvert...
r11165 os.path.join("..", "templates"), config=True,
Jonathan Frederic
Finished rename/refact on API namespace
r10690 help="Path where the template files are located.")
template_skeleton_path = Unicode(
MinRK
Don't hardcode posix paths in nbconvert...
r11165 os.path.join("..", "templates", "skeleton"), config=True,
Jonathan Frederic
Finished rename/refact on API namespace
r10690 help="Path where the template skeleton files are located.")
#Jinja block definitions
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 jinja_comment_block_start = Unicode("", config=True)
jinja_comment_block_end = Unicode("", config=True)
jinja_variable_block_start = Unicode("", config=True)
jinja_variable_block_end = Unicode("", config=True)
jinja_logic_block_start = Unicode("", config=True)
jinja_logic_block_end = Unicode("", config=True)
Jonathan Frederic
Finished rename/refact on API namespace
r10690
Jonathan Frederic
Fixed all broken references, refactored some stuff here and there,...
r10624 #Extension that the template files use.
Jonathan Frederic
Finished rename/refact on API namespace
r10690 template_extension = Unicode(".tpl", config=True)
Jonathan Frederic
Fixed all broken references, refactored some stuff here and there,...
r10624
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.
Matthias BUSSONNIER
Do not use mutable class defautl parameter...
r10799 transformers = None
Matthias BUSSONNIER
stateless converter
r9640
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677 def __init__(self, transformers=None, filters=None, config=None, **kw):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Public constructor
Jonathan Frederic
Post code-review, extended refactor.
r10485
Jonathan Frederic
Finished rename/refact on API namespace
r10690 Parameters
----------
transformers : list[of transformer]
Custom transformers to apply to the notebook prior to engaging
the Jinja template engine. Any transformers specified here
will override existing transformers if a naming conflict
occurs.
Matthias BUSSONNIER
fix filters documentation....
r10838 filters : dict[of filter]
filters specified here will override existing filters if a naming
conflict occurs. Filters are availlable in jinja template through
the name of the corresponding key. Cf class docstring for
availlable default filters.
Jonathan Frederic
Finished rename/refact on API namespace
r10690 config : config
User configuration instance.
"""
Jonathan Frederic
Removed "profiles"... Templates that are shipped with nbconvert by default should...
r10435 #Call the base class constructor
Matthias BUSSONNIER
fix config inheriting
r10963 c = self.default_config
if config:
c.merge(config)
super(Exporter, self).__init__(config=c, **kw)
Matthias BUSSONNIER
document
r9665
Jonathan Frederic
Moved latex code into latex exporter
r10480 #Standard environment
Jonathan Frederic
Post code-review, extended refactor.
r10485 self._init_environment()
Matthias BUSSONNIER
create configurable preprocessors
r9624
Jonathan Frederic
Added latexexporter
r10587 #Add transformers
self._register_transformers()
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
More clean-up. Nomenclature changes
r10578 self._register_filters()
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677 #Load user transformers. Overwrite existing transformers if need be.
Matthias BUSSONNIER
Do not use mutable class defautl parameter...
r10799 if transformers :
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677 for transformer in transformers:
self.register_transformer(transformer)
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 #Load user filters. Overwrite existing filters if need be.
Jonathan Frederic
Cleanup and refactor of API, almost complete....
r10677 if not filters is None:
for key, user_filter in filters.iteritems():
Jake Vanderplas
use register_filter() for registering user filters
r11116 self.register_filter(key, user_filter)
Matthias BUSSONNIER
start tinkerign with config system
r10862
@property
def default_config(self):
Matthias BUSSONNIER
fix config inheriting
r10963 return Config()
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
Matthias BUSSONNIER
allow to pass a resource dict with notebook...
r10837 def from_notebook_node(self, nb, resources=None):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Convert a notebook from a notebook node instance.
Parameters
----------
nb : Notebook node
Matthias BUSSONNIER
allow to pass a resource dict with notebook...
r10837 resources : a dict of additional resources that
can be accessed read/write by transformers
and filters.
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Matthias BUSSONNIER
allow to pass a resource dict with notebook...
r10837 if resources is None:
resources = {}
nb, resources = self._preprocess(nb, resources)
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
#Load the template file.
Jonathan Frederic
Fixed all broken references, refactored some stuff here and there,...
r10624 self.template = self.environment.get_template(self.template_file+self.template_extension)
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
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
Finished rename/refact on API namespace
r10690 """
Convert a notebook from a notebook file.
Parameters
----------
filename : str
Full filename of the notebook file to open and convert.
"""
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 with io.open(filename) as f:
Jonathan Frederic
More clean-up. Nomenclature changes
r10578 return self.from_notebook_node(nbformat.read(f, 'json'))
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
Jonathan Frederic
Create exceptions file to house all of the convert specific exceptions....
r10431 def from_file(self, file_stream):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Convert a notebook from a notebook file.
Parameters
----------
file_stream : file-like object
Notebook file-like object to convert.
"""
Jonathan Frederic
More clean-up. Nomenclature changes
r10578 return self.from_notebook_node(nbformat.read(file_stream, 'json'))
Jonathan Frederic
Added latexexporter
r10587 def register_transformer(self, transformer):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Register a transformer.
Transformers are classes that act upon the notebook before it is
passed into the Jinja templating engine. Transformers are also
capable of passing additional information to the Jinja
templating engine.
Parameters
----------
transformer : transformer
"""
Jonathan Frederic
Fixed None transformers error.
r10695 if self.transformers is None:
self.transformers = []
Jonathan Frederic
Finished rename/refact on API namespace
r10690
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 if inspect.isfunction(transformer):
Jonathan Frederic
Renamed preprocessors to transformers to maintain consistency
r10694 self.transformers.append(transformer)
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 return transformer
elif isinstance(transformer, MetaHasTraits):
Jonathan Frederic
Fixed all broken references, refactored some stuff here and there,...
r10624 transformer_instance = transformer(config=self.config)
Jonathan Frederic
Renamed preprocessors to transformers to maintain consistency
r10694 self.transformers.append(transformer_instance)
Jonathan Frederic
Fixed all broken references, refactored some stuff here and there,...
r10624 return transformer_instance
Jonathan Frederic
Added latexexporter
r10587 else:
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 transformer_instance = transformer()
Jonathan Frederic
Renamed preprocessors to transformers to maintain consistency
r10694 self.transformers.append(transformer_instance)
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 return transformer_instance
Jonathan Frederic
Added latexexporter
r10587
Jonathan Frederic
More clean-up. Nomenclature changes
r10578 def register_filter(self, name, filter):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Register a filter.
A filter is a function that accepts and acts on one string.
The filters are accesible within the Jinja templating engine.
Parameters
----------
name : str
name to give the filter in the Jinja engine
filter : filter
"""
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 if inspect.isfunction(filter):
self.environment.filters[name] = filter
elif isinstance(filter, MetaHasTraits):
Jonathan Frederic
Added latexexporter
r10587 self.environment.filters[name] = filter(config=self.config)
Jonathan Frederic
More clean-up. Nomenclature changes
r10578 else:
Jonathan Frederic
Fixed problem with data type filter construction.
r10631 self.environment.filters[name] = filter()
Jonathan Frederic
Finished a rough draft of the exporters.
r10588 return self.environment.filters[name]
Jonathan Frederic
More clean-up. Nomenclature changes
r10578
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
Jonathan Frederic
Added latexexporter
r10587 def _register_transformers(self):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Register all of the transformers needed for this exporter.
"""
Jonathan Frederic
Renamed preprocessors to transformers to maintain consistency
r10694
Brian E. Granger
Fixing import for nbconvert.
r11089 self.register_transformer(transformers.coalesce_streams)
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
#Remember the figure extraction transformer so it can be enabled and
#disabled easily later.
Brian E. Granger
Fixing import for nbconvert.
r11089 self.extract_figure_transformer = self.register_transformer(transformers.ExtractFigureTransformer)
Jonathan Frederic
Added latexexporter
r10587
Jonathan Frederic
More clean-up. Nomenclature changes
r10578 def _register_filters(self):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Register all of the filters required for the exporter.
"""
Matthias BUSSONNIER
pylint plus sphinx default to non-interactive.
r10875 for k, v in default_filters.iteritems():
self.register_filter(k, v)
Jonathan Frederic
Finished a rough draft of the exporters.
r10588
Jonathan Frederic
Post code-review, extended refactor.
r10485 def _init_environment(self):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Create the Jinja templating environment.
"""
MinRK
fix path prefix in nbconvert...
r11197 here = os.path.dirname(os.path.realpath(__file__))
Jonathan Frederic
Added latexexporter
r10587 self.environment = Environment(
Jonathan Frederic
Post code-review, extended refactor.
r10485 loader=FileSystemLoader([
MinRK
Don't hardcode posix paths in nbconvert...
r11165 os.path.join(here, self.template_path),
os.path.join(here, self.template_skeleton_path),
Jonathan Frederic
Post code-review, extended refactor.
r10485 ]),
extensions=JINJA_EXTENSIONS
)
Jonathan Frederic
Finished rename/refact on API namespace
r10690
#Set special Jinja2 syntax that will not conflict with latex.
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_logic_block_start:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.block_start_string = self.jinja_logic_block_start
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_logic_block_end:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.block_end_string = self.jinja_logic_block_end
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_variable_block_start:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.variable_start_string = self.jinja_variable_block_start
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_variable_block_end:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.variable_end_string = self.jinja_variable_block_end
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_comment_block_start:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.comment_start_string = self.jinja_comment_block_start
Jonathan Frederic
Fixed error due to Unicode traitlets not supporting None type.
r10693 if self.jinja_comment_block_end:
Jonathan Frederic
Finished rename/refact on API namespace
r10690 self.environment.comment_end_string = self.jinja_comment_block_end
Jonathan Frederic
Post code-review, extended refactor.
r10485
Matthias BUSSONNIER
allow to pass a resource dict with notebook...
r10837 def _preprocess(self, nb, resources):
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Preprocess the notebook before passing it into the Jinja engine.
To preprocess the notebook is to apply all of the
Parameters
----------
nb : notebook node
notebook that is being exported.
Matthias BUSSONNIER
allow to pass a resource dict with notebook...
r10837 resources : a dict of additional resources that
can be accessed read/write by transformers
and filters.
Jonathan Frederic
Finished rename/refact on API namespace
r10690 """
Matthias BUSSONNIER
to clean (transformer deepcopy)
r10867 # Do a deepcopy first,
# we are never safe enough with what the transformers could do.
nbc = deepcopy(nb)
resc = deepcopy(resources)
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 #Run each transformer on the notebook. Carry the output along
#to each transformer
Jonathan Frederic
Renamed preprocessors to transformers to maintain consistency
r10694 for transformer in self.transformers:
Matthias BUSSONNIER
to clean (transformer deepcopy)
r10867 nb, resources = transformer(nbc, resc)
Jonathan Frederic
Removed uneccessary jinja_filters class. Merged code into exporter class....
r10432 return nb, resources
Matthias BUSSONNIER
fix filters documentation....
r10838