diff --git a/nbconvert/__init__.py b/nbconvert/__init__.py old mode 100644 new mode 100755 diff --git a/nbconvert/api/base.py b/nbconvert/api/base.py index 4279ee5..96b9bd4 100755 --- a/nbconvert/api/base.py +++ b/nbconvert/api/base.py @@ -23,7 +23,6 @@ from __future__ import print_function, absolute_import # Stdlib imports import io import os -import re # IPython imports from IPython.config.configurable import Configurable @@ -35,16 +34,19 @@ from IPython.utils.text import indent from jinja2 import Environment, FileSystemLoader from markdown import markdown -# local import (pre-transformers) -from exceptions import ConversionException -from . import transformers as trans #TODO -from .utils import get_lines #TODO -from .utils import remove_ansi #TODO -from .utils import highlight, ansi2html #TODO +# 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 -import .utils.strings as strings -import .utils.markdown as markdown_utils -import .utils.datatypefilter.DataTypeFilter as DataTypeFilter #----------------------------------------------------------------------------- # Globals and constants @@ -64,7 +66,7 @@ JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols'] class Exporter(Configurable): """ A Jinja2 base converter templates - Preprocess the ipynb files, feed it throug jinja templates, + Pre-process the IPYNB files, feed it through Jinja2 templates, and spit an converted files and a data object with other data should be mostly configurable """ @@ -72,17 +74,11 @@ class Exporter(Configurable): pre_transformer_order = List(['haspyout_transformer'], config=True, help= """ - An ordered list of pre transformer to apply to the ipynb + An ordered list of pre-transformer to apply to the IPYNB file before running through templates """ ) -#TODO: Flagged for removal. - tex_environement = Bool( - False, - config=True, - help=" Whether or not the user is exporting to latex.") - template_file = Unicode( '', config=True, help="Name of the template file to use") @@ -94,7 +90,7 @@ class Exporter(Configurable): stdout = Bool( True, config=True, - help="""Whether to print the converted ipynb file to stdout + help="""Whether to print the converted IPYNB file to stdout "use full do diff files without actually writing a new file""" ) @@ -130,67 +126,46 @@ class Exporter(Configurable): user defined filter will overwrite the one availlable by default. """ - #Merge default config options with user specific override options. - default_config = self._get_default_options() + #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 + if not config == None: default_config._merge(config) - config = default_config - + config = default_config + #Call the base class constructor super(Exporter, self).__init__(config=config, **kw) #Standard environment self.ext = TEMPLATE_EXTENSION - 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 - ) + self._init_environment() - 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) + #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) #For compatibility, TODO: remove later. - self.preprocessors.append(trans.coalesce_streams) - self.preprocessors.append(trans.ExtractFigureTransformer(config=config)) - self.preprocessors.append(trans.RevealHelpTransformer(config=config)) - self.preprocessors.append(trans.CSSHtmlHeaderTransformer(config=config)) - self.preprocessors.append(LatexTransformer(config=config)) - - #Only load the sphinx transformer if the file reference worked - #(Sphinx dependencies exist on the user's machine.) - if SphinxTransformer: - self.preprocessors.append(SphinxTransformer(config=config)) + 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)) #Add filters to the Jinja2 environment - self.env.filters['filter_data_type'] = DataTypeFilter(config=config) - self.env.filters['pycomment'] = _python_comment - self.env.filters['indent'] = indent - self.env.filters['rm_fake'] = _rm_fake - self.env.filters['rm_ansi'] = remove_ansi - self.env.filters['markdown'] = markdown - self.env.filters['ansi2html'] = ansi2html - self.env.filters['markdown2latex'] = markdown_utils.markdown2latex - self.env.filters['markdown2rst'] = markdown_utils.markdown2rst - self.env.filters['get_lines'] = get_lines - self.env.filters['wrap'] = strings.wrap - self.env.filters['rm_dollars'] = strings.strip_dollars - self.env.filters['rm_math_space'] = rm_math_space - self.env.filters['highlight2html'] = highlight - self.env.filters['highlight2latex'] = highlight2latex - - #Latex specific filters - if self.tex_environement: - self.env.filters['escape_tex'] = _escape_tex - self.env.filters['highlight'] = highlight2latex - else: - self.env.filters['highlight'] = highlight + self._register_filters(config) #Load user filters. Overwrite existing filters if need be. for key, user_filter in jinja_filters.iteritems(): @@ -243,6 +218,36 @@ class Exporter(Configurable): return self.export(nbformat.read(file_stream, 'json')) + 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 + + def _preprocess(self, nb): """ Preprocess the notebook using the transformers specific for the current export format. @@ -259,75 +264,3 @@ class Exporter(Configurable): nb, resources = transformer(nb, resources) return nb, resources - - def _get_default_options(self, export_format): - """ Load the default options for built in formats. - - export_format: Format being exported to. - """ - - c = get_config() - - #Set default data extraction priorities. - c.GlobalConfigurable.display_data_priority =['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - c.ExtractFigureTransformer.display_data_priority=['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - c.ConverterTemplate.display_data_priority= ['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - - #For most (or all cases), the template file name matches the format name. - c.ConverterTemplate.template_file = export_format - - if export_format == "basichtml" or "fullhtml" or "reveal": - c.CSSHtmlHeaderTransformer.enabled=True - if export_format == 'reveal' - c.NbconvertApp.fileext='reveal.html' - else: - c.NbconvertApp.fileext='html' - - elif export_format == "latex_sphinx_howto" or export_format == "latex_sphinx_manual": - - #Turn on latex environment - c.ConverterTemplate.tex_environement=True - - #Standard latex extension - c.NbconvertApp.fileext='tex' - - #Prioritize latex extraction for latex exports. - c.GlobalConfigurable.display_data_priority =['latex', 'svg', 'png', 'jpg', 'jpeg' , 'text'] - c.ExtractFigureTransformer.display_data_priority=['latex', 'svg', 'png', 'jpg', 'jpeg'] - c.ExtractFigureTransformer.extra_ext_map={'svg':'pdf'} - c.ExtractFigureTransformer.enabled=True - - # Enable latex transformers (make markdown2latex work with math $.) - c.LatexTransformer.enabled=True - c.SphinxTransformer.enabled = True - - elif export_format == 'markdown': - c.NbconvertApp.fileext='md' - c.ExtractFigureTransformer.enabled=True - - elif export_format == 'python': - c.NbconvertApp.fileext='py' - - - elif export_format == 'rst': - c.NbconvertApp.fileext='rst' - c.ExtractFigureTransformer.enabled=True - return c - - - #TODO: Comment me. - def _rm_fake(strng): - return strng.replace('/files/', '') - - - #TODO: Comment me. - def _python_comment(string): - return '# '+'\n# '.join(string.split('\n')) - - - #TODO: Comment me. - def _escape_tex(value): - newval = value - for pattern, replacement in LATEX_SUBS: - newval = pattern.sub(replacement, newval) - return newval \ No newline at end of file diff --git a/nbconvert/api/converter.py b/nbconvert/api/converter.py new file mode 100755 index 0000000..2f6eb40 --- /dev/null +++ b/nbconvert/api/converter.py @@ -0,0 +1,23 @@ +"""Latex transformer. + +Module that allows latex output notebooks to be conditioned before +they are converted. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2013, 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. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Functions +#----------------------------------------------------------------------------- +def export_sphinx_report(nb, config=None): + pass +def export_sphinx_report(nb, fileName, config=None): + pass + +#TODO: Add basic export/import utility functions. +__author__ = 'root' diff --git a/nbconvert/api/latex.py b/nbconvert/api/latex.py old mode 100644 new mode 100755 index 17e6c97..9811135 --- a/nbconvert/api/latex.py +++ b/nbconvert/api/latex.py @@ -1,5 +1,4 @@ - -"""Latex exporter for the notebook conversion pipeline. + """Latex exporter for the notebook conversion pipeline. This module defines Exporter, a highly configurable converter that uses Jinja2 to export notebook files into different format. @@ -19,9 +18,7 @@ befor conversion and jinja filter that would then be availlable in the templates #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- -from .utils import highlight2latex #TODO - -from .transformers.latex import LatexTransformer, rm_math_space #TODO: rm_math_space from filters +import base.Exporter as Exporter #Try to import the Sphinx exporter. If the user doesn't have Sphinx isntalled #on his/her machine, fail silently. @@ -44,20 +41,10 @@ LATEX_JINJA_COMMENT_BLOCK = ["((=", "=))"] LATEX_JINJA_VARIABLE_BLOCK = ["(((", ")))"] LATEX_JINJA_LOGIC_BLOCK = ["((*", "*))"] -#Latex substitutions for escaping latex. -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'), -) - #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- -class LatexExporter(Configurable): +class LatexExporter(Exporter): """ A Jinja2 base converter templates Preprocess the ipynb files, feed it throug jinja templates, @@ -149,29 +136,9 @@ class LatexExporter(Configurable): self.preprocessors.append(SphinxTransformer(config=config)) #Add filters to the Jinja2 environment - self.env.filters['filter_data_type'] = DataTypeFilter(config=config) - self.env.filters['pycomment'] = _python_comment - self.env.filters['indent'] = indent - self.env.filters['rm_fake'] = _rm_fake - self.env.filters['rm_ansi'] = remove_ansi - self.env.filters['markdown'] = markdown - self.env.filters['ansi2html'] = ansi2html - self.env.filters['markdown2latex'] = markdown_utils.markdown2latex - self.env.filters['markdown2rst'] = markdown_utils.markdown2rst - self.env.filters['get_lines'] = get_lines - self.env.filters['wrap'] = strings.wrap - self.env.filters['rm_dollars'] = strings.strip_dollars - self.env.filters['rm_math_space'] = rm_math_space - self.env.filters['highlight2html'] = highlight - self.env.filters['highlight2latex'] = highlight2latex - - #Latex specific filters - if self.tex_environement: - self.env.filters['escape_tex'] = _escape_tex - self.env.filters['highlight'] = highlight2latex - else: - self.env.filters['highlight'] = highlight - + self.env.filters['escape_tex'] = filters.latex.escape_tex + self.env.filters['highlight'] = filters.pygments.highlight2latex + #Load user filters. Overwrite existing filters if need be. for key, user_filter in jinja_filters.iteritems(): if isinstance(user_filter, MetaHasTraits): @@ -181,115 +148,3 @@ class LatexExporter(Configurable): #Load the template file. self.template = self.env.get_template(self.template_file+self.ext) - - - 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. - """ - - nb, resources = self._preprocess(nb) - return self.template.render(nb=nb, resources=resources), resources - - - def from_filename(self, filename): - """Read and export a notebook from a filename - - filename: Filename of the notebook file to export. - - Returns both the converted ipynb file and a dict containing the - resources created along the way via the transformers and Jinja2 - processing. - """ - with io.open(filename) as f: - return self.export(nbformat.read(f, 'json')) - - - def from_file(self, file_stream): - """Read and export a notebook from a filename - - file_stream: File handle of file that contains notebook data. - - Returns both the converted ipynb file and a dict containing the - resources created along the way via the transformers and Jinja2 - processing. - """ - - return self.export(nbformat.read(file_stream, 'json')) - - - 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 - - - def _get_default_options(self, export_format): - """ Load the default options for built in formats. - - export_format: Format being exported to. - """ - - c = get_config() - - #Set default data extraction priorities. - c.GlobalConfigurable.display_data_priority =['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - c.ExtractFigureTransformer.display_data_priority=['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - c.ConverterTemplate.display_data_priority= ['svg', 'png', 'latex', 'jpg', 'jpeg','text'] - - #For most (or all cases), the template file name matches the format name. - c.ConverterTemplate.template_file = export_format - - if export_format == "basichtml" or "fullhtml" or "reveal": - c.CSSHtmlHeaderTransformer.enabled=True - if export_format == 'reveal' - c.NbconvertApp.fileext='reveal.html' - else: - c.NbconvertApp.fileext='html' - - elif export_format == "latex_sphinx_howto" or export_format == "latex_sphinx_manual": - - #Turn on latex environment - c.ConverterTemplate.tex_environement=True - - #Standard latex extension - c.NbconvertApp.fileext='tex' - - #Prioritize latex extraction for latex exports. - c.GlobalConfigurable.display_data_priority =['latex', 'svg', 'png', 'jpg', 'jpeg' , 'text'] - c.ExtractFigureTransformer.display_data_priority=['latex', 'svg', 'png', 'jpg', 'jpeg'] - c.ExtractFigureTransformer.extra_ext_map={'svg':'pdf'} - c.ExtractFigureTransformer.enabled=True - - # Enable latex transformers (make markdown2latex work with math $.) - c.LatexTransformer.enabled=True - c.SphinxTransformer.enabled = True - - elif export_format == 'markdown': - c.NbconvertApp.fileext='md' - c.ExtractFigureTransformer.enabled=True - - elif export_format == 'python': - c.NbconvertApp.fileext='py' - - - elif export_format == 'rst': - c.NbconvertApp.fileext='rst' - c.ExtractFigureTransformer.enabled=True - return c \ No newline at end of file diff --git a/nbconvert/filters/ansi.py b/nbconvert/filters/ansi.py new file mode 100644 index 0000000..d382ad7 --- /dev/null +++ b/nbconvert/filters/ansi.py @@ -0,0 +1,82 @@ +# ANSI color functions: +import re +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) + + +def ansi2html(txt): + """Render ANSI colors as HTML colors + + This is equivalent to util.fixConsole in utils.js + + Parameters + ---------- + txt : string + + Returns + ------- + string + """ + + ansi_colormap = { + '30': 'ansiblack', + '31': 'ansired', + '32': 'ansigreen', + '33': 'ansiyellow', + '34': 'ansiblue', + '35': 'ansipurple', + '36': 'ansicyan', + '37': 'ansigrey', + '01': 'ansibold', + } + + # do ampersand first + txt = txt.replace('&', '&') + html_escapes = { + '<': '<', + '>': '>', + "'": ''', + '"': '"', + '`': '`', + } + for c, escape in html_escapes.iteritems(): + txt = txt.replace(c, escape) + + ansi_re = re.compile('\x1b' + r'\[([\dA-Fa-f;]*?)m') + m = ansi_re.search(txt) + opened = False + cmds = [] + opener = '' + closer = '' + while m: + cmds = m.groups()[0].split(';') + closer = '' if opened else '' + # True if there is there more than one element in cmds, *or* + # if there is only one but it is not equal to a string of zeroes. + opened = len(cmds) > 1 or cmds[0] != '0' * len(cmds[0]) + classes = [] + for cmd in cmds: + if cmd in ansi_colormap: + classes.append(ansi_colormap.get(cmd)) + + if classes: + opener = '' % (' '.join(classes)) + else: + opener = '' + txt = re.sub(ansi_re, closer + opener, txt, 1) + + m = ansi_re.search(txt) + + if opened: + txt += '' + return txt diff --git a/nbconvert/filters/datatypefilter.py b/nbconvert/filters/datatypefilter.py old mode 100644 new mode 100755 index 7ac1239..5167c25 --- a/nbconvert/filters/datatypefilter.py +++ b/nbconvert/filters/datatypefilter.py @@ -20,7 +20,7 @@ class DataTypeFilter(GlobalConfigurable): """ Returns the prefered display format """ def __init__(self, config=None, **kw): - super(FilterDataType, self).__init__(config=config, **kw) + super(DataTypeFilter, self).__init__(config=config, **kw) def __call__(self, output): """ Return the first available format in the priority """ diff --git a/nbconvert/filters/latex.py b/nbconvert/filters/latex.py old mode 100644 new mode 100755 index 205dea6..63e1293 --- a/nbconvert/filters/latex.py +++ b/nbconvert/filters/latex.py @@ -14,11 +14,34 @@ they are converted. #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- -from __future__ import print_function +import re + +#----------------------------------------------------------------------------- +# Globals and constants +#----------------------------------------------------------------------------- + +#Latex substitutions for escaping latex. +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'), +) #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- + +#TODO: Comment me. +def escape_tex(value): + newval = value + for pattern, replacement in LATEX_SUBS: + newval = pattern.sub(replacement, newval) + return newval + + def rm_math_space(text): """ Remove the space between latex math commands and enclosing $ symbols. diff --git a/nbconvert/filters/markdown.py b/nbconvert/filters/markdown.py old mode 100644 new mode 100755 index 7f0e75f..4a6324c --- a/nbconvert/filters/markdown.py +++ b/nbconvert/filters/markdown.py @@ -17,11 +17,13 @@ markdown. from __future__ import print_function # Stdlib imports +import sys import subprocess #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- + # Pandoc-dependent code def markdown2latex(src): """Convert a markdown string to LaTeX via pandoc. diff --git a/nbconvert/filters/pygments.py b/nbconvert/filters/pygments.py new file mode 100644 index 0000000..4c1ba3c --- /dev/null +++ b/nbconvert/filters/pygments.py @@ -0,0 +1,39 @@ +# Our own imports +from utils.lexers import IPythonLexer + +#----------------------------------------------------------------------------- +# Globals and constants +#----------------------------------------------------------------------------- +_multiline_outputs = ['text', 'html', 'svg', 'latex', 'javascript', 'json'] + + +#----------------------------------------------------------------------------- +# Utility functions +#----------------------------------------------------------------------------- +def highlight(src, lang='ipython'): + """ + Return a syntax-highlighted version of the input source as html output. + """ + from pygments.formatters import HtmlFormatter + return pygment_highlight(src, HtmlFormatter(), lang) + +def highlight2latex(src, lang='ipython'): + """ + Return a syntax-highlighted version of the input source as latex output. + """ + from pygments.formatters import LatexFormatter + return pygment_highlight(src, LatexFormatter(), lang) + +def pygment_highlight(src, output_formatter, lang='ipython'): + """ + Return a syntax-highlighted version of the input source + """ + from pygments import highlight + from pygments.lexers import get_lexer_by_name + + if lang == 'ipython': + lexer = IPythonLexer() + else: + lexer = get_lexer_by_name(lang, stripall=True) + + return highlight(src, lexer, output_formatter) diff --git a/nbconvert/filters/strings.py b/nbconvert/filters/strings.py old mode 100644 new mode 100755 index 83141a8..f302be3 --- a/nbconvert/filters/strings.py +++ b/nbconvert/filters/strings.py @@ -1,4 +1,4 @@ - """String utilities. +"""String utilities. Contains a collection of usefull string manipulations functions. """ @@ -32,4 +32,26 @@ def wrap(text, width=100): def strip_dollars(text): """Remove all dollar symbols from text""" - return text.strip('$') \ No newline at end of file + return text.strip('$') + + +#TODO: Comment me. +def rm_fake(strng): + return strng.replace('/files/', '') + + +#TODO: Comment me. +def python_comment(string): + return '# '+'\n# '.join(string.split('\n')) + +def get_lines(src, start=None,end=None): + """ + Split the input text into separate lines and then return the + lines that the caller is interested in. + """ + + # Split the input into lines. + lines = src.split("\n") + + # Return the right lines. + return "\n".join(lines[start:end]) #re-join diff --git a/nbconvert/transformers/activatable.py b/nbconvert/transformers/activatable.py old mode 100644 new mode 100755 index e59f235..ad0abfb --- a/nbconvert/transformers/activatable.py +++ b/nbconvert/transformers/activatable.py @@ -1,4 +1,6 @@ - +from transformers.base import ConfigurableTransformers + + class ActivatableTransformer(ConfigurableTransformers): """A simple ConfigurableTransformers that have an enabled flag @@ -15,4 +17,3 @@ class ActivatableTransformer(ConfigurableTransformers): return nb, other else : return super(ActivatableTransformer, self).__call__(nb, other) - diff --git a/nbconvert/transformers/base.py b/nbconvert/transformers/base.py index 01ddf79..b5420b0 100755 --- a/nbconvert/transformers/base.py +++ b/nbconvert/transformers/base.py @@ -57,6 +57,7 @@ class ConfigurableTransformers(GlobalConfigurable): You should return modified cell and resource dict. """ + raise NotImplementedError('should be implemented by subclass') return cell, other diff --git a/nbconvert/transformers/coalescestreams.py b/nbconvert/transformers/coalescestreams.py new file mode 100644 index 0000000..6684a2c --- /dev/null +++ b/nbconvert/transformers/coalescestreams.py @@ -0,0 +1,43 @@ + +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 coalesce_streams(cell, other, count): + """merge consecutive sequences of stream output into single stream + +to prevent extra newlines inserted at flush calls + +TODO: handle \r deletion +""" + outputs = cell.get('outputs', []) + if not outputs: + return cell, other + new_outputs = [] + last = outputs[0] + new_outputs = [last] + for output in outputs[1:]: + if (output.output_type == 'stream' and + last.output_type == 'stream' and + last.stream == output.stream + ): + last.text += output.text + else: + new_outputs.append(output) + + cell.outputs = new_outputs + return cell, other + diff --git a/nbconvert/transformers/csshtmlheader.py b/nbconvert/transformers/csshtmlheader.py old mode 100644 new mode 100755 diff --git a/nbconvert/transformers/extractfigure.py b/nbconvert/transformers/extractfigure.py old mode 100644 new mode 100755 diff --git a/nbconvert/transformers/latex.py b/nbconvert/transformers/latex.py old mode 100644 new mode 100755 diff --git a/nbconvert/transformers/reavealhelp.py b/nbconvert/transformers/revealhelp.py old mode 100644 new mode 100755 similarity index 100% rename from nbconvert/transformers/reavealhelp.py rename to nbconvert/transformers/revealhelp.py diff --git a/nbconvert/transformers/sphinx.py b/nbconvert/transformers/sphinx.py old mode 100644 new mode 100755 diff --git a/nbconvert1/converters/lexers.py b/nbconvert/utils/lexers.py similarity index 100% rename from nbconvert1/converters/lexers.py rename to nbconvert/utils/lexers.py