diff --git a/IPython/nbconvert/exporters/basichtml.py b/IPython/nbconvert/exporters/basichtml.py index 1559aaa..8f09293 100644 --- a/IPython/nbconvert/exporters/basichtml.py +++ b/IPython/nbconvert/exporters/basichtml.py @@ -14,7 +14,7 @@ Exporter that exports Basic HTML. # Imports #----------------------------------------------------------------------------- -from IPython.utils.traitlets import Unicode +from IPython.utils.traitlets import Unicode, List from ..transformers.csshtmlheader import CSSHTMLHeaderTransformer @@ -41,15 +41,10 @@ class BasicHTMLExporter(Exporter): 'basichtml', config=True, help="Name of the template file to use") - - def _register_transformers(self): - """ - Register all of the transformers needed for this exporter. - """ - - #Register the transformers of the base class. - super(BasicHTMLExporter, self)._register_transformers() - - #Register CSSHTMLHeaderTransformer transformer - self.register_transformer(CSSHTMLHeaderTransformer) - + default_transformers = List([transformers.coalesce_streams, + transformers.ExtractFigureTransformer, + transformers.CSSHTMLHeaderTransformer], + config=True, + help="""List of transformers available by default, by name, namespace, + instance, or type.""") + \ No newline at end of file diff --git a/IPython/nbconvert/exporters/exporter.py b/IPython/nbconvert/exporters/exporter.py index 10cb993..de2eaf1 100755 --- a/IPython/nbconvert/exporters/exporter.py +++ b/IPython/nbconvert/exporters/exporter.py @@ -21,7 +21,9 @@ import io import os import inspect import types -from copy import deepcopy +import copy +import collections +import datetime # other libs/dependencies from jinja2 import Environment, FileSystemLoader, ChoiceLoader @@ -34,8 +36,8 @@ from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, Li from IPython.utils.importstring import import_item from IPython.utils.text import indent +from IPython.nbconvert import transformers as nbtransformers from IPython.nbconvert import filters -from IPython.nbconvert import transformers #----------------------------------------------------------------------------- # Globals and constants @@ -115,9 +117,16 @@ class Exporter(Configurable): #Configurability, allows the user to easily add filters and transformers. transformers = List(config=True, help="""List of transformers, by name or namespace, to enable.""") + filters = Dict(config=True, help="""Dictionary of filters, by name and namespace, to add to the Jinja environment.""") + + default_transformers = List([nbtransformers.coalesce_streams, + nbtransformers.ExtractFigureTransformer], + config=True, + help="""List of transformers available by default, by name, namespace, + instance, or type.""") def __init__(self, config=None, extra_loaders=None, **kw): """ @@ -139,25 +148,10 @@ class Exporter(Configurable): super(Exporter, self).__init__(config=c, **kw) - #Standard environment + #Init self._init_environment(extra_loaders=extra_loaders) - - #Add transformers - self._transformers = [] - self._register_transformers() - - #Add filters to the Jinja2 environment - self._register_filters() - - #Load user transformers. Enabled by default. - if self.transformers: - for transformer in self.transformers: - self.register_transformer(transformer, enabled=True) - - #Load user filters. Overwrite existing filters if need be. - if self.filters: - for key, user_filter in self.filters.iteritems(): - self.register_filter(key, user_filter) + self._init_transformers() + self._init_filters() @property @@ -176,11 +170,8 @@ class Exporter(Configurable): of additional resources that can be accessed read/write by transformers and filters. """ - nb_copy = deepcopy(nb) - - #Set output extension in resources dict - #TODO: init_resources - resources['output_extension'] = self.file_extension + nb_copy = copy.deepcopy(nb) + resources = self._init_resources(resources) #Preprocess nb_copy, resources = self._transform(nb_copy, resources) @@ -200,6 +191,16 @@ class Exporter(Configurable): filename : str Full filename of the notebook file to open and convert. """ + + #Pull the metadata from the filesystem. + if not 'metadata' in resources: + resources['metadata'] = ResourcesDict() + basename = os.path.basename(filename) + notebook_name = basename[:basename.rfind('.')] + resources['metadata']['name'] = notebook_name + + modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename)) + resources['metadata']['modified_date'] = modified_date.strftime("%B %-d, %Y") with io.open(filename) as f: return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw) @@ -281,24 +282,6 @@ class Exporter(Configurable): self.environment.filters[name] = filter() return self.environment.filters[name] - - def _register_transformers(self): - """ - Register all of the transformers needed for this exporter, disabled - unless specified explicitly. - """ - - self.register_transformer(transformers.coalesce_streams) - self.register_transformer(transformers.ExtractFigureTransformer) - - - def _register_filters(self): - """ - Register all of the filters required for the exporter. - """ - for key, value in default_filters.iteritems(): - self.register_filter(key, value) - def _init_environment(self, extra_loaders=None): """ @@ -333,6 +316,63 @@ class Exporter(Configurable): if self.jinja_comment_block_end: self.environment.comment_end_string = self.jinja_comment_block_end + + def _init_transformers(self): + """ + Register all of the transformers needed for this exporter, disabled + unless specified explicitly. + """ + self._transformers = [] + + #Load default transformers (not necessarly enabled by default). + if self.default_transformers: + for transformer in self.default_transformers: + self.register_transformer(transformer) + + #Load user transformers. Enable by default. + if self.transformers: + for transformer in self.transformers: + self.register_transformer(transformer, enabled=True) + + + def _init_filters(self): + """ + Register all of the filters required for the exporter. + """ + + #Add default filters to the Jinja2 environment + for key, value in default_filters.iteritems(): + self.register_filter(key, value) + + #Load user filters. Overwrite existing filters if need be. + if self.filters: + for key, user_filter in self.filters.iteritems(): + self.register_filter(key, user_filter) + + + def _init_resources(self, resources): + + #Make sure the resources dict is of ResourcesDict type. + if resources is None: + resources = ResourcesDict() + if not isinstance(resources, ResourcesDict): + new_resources = ResourcesDict() + new_resources.update(resources) + resources = new_resources + + #Make sure the metadata extension exists in resources + if 'metadata' in resources: + if not isinstance(resources['metadata'], ResourcesDict): + resources['metadata'] = ResourcesDict(resources['metadata']) + else: + resources['metadata'] = ResourcesDict() + resources['metadata']['name'] = 'Notebook' + resources['metadata']['modified_date'] = '' + + #Set the output extension + resources['output_extension'] = self.file_extension + return resources + def _transform(self, nb, resources): """ diff --git a/IPython/nbconvert/exporters/latex.py b/IPython/nbconvert/exporters/latex.py index 055b64c..01d235a 100755 --- a/IPython/nbconvert/exporters/latex.py +++ b/IPython/nbconvert/exporters/latex.py @@ -20,7 +20,7 @@ tags to circumvent Jinja/Latex syntax conflicts. import os # IPython imports -from IPython.utils.traitlets import Unicode +from IPython.utils.traitlets import Unicode, List from IPython.config import Config from IPython.nbconvert import filters, transformers @@ -68,44 +68,43 @@ class LatexExporter(Exporter): #Extension that the template files use. template_extension = Unicode(".tplx", config=True) - def _register_filters(self): + default_transformers = List([transformers.ExtractFigureTransformer, + transformers.CSSHTMLHeaderTransformer, + transformers.LatexTransformer, + transformers.Svg2PdfTransformer], + config=True, + help="""List of transformers available by default, by name, namespace, + instance, or type.""") + + + def _init_filters(self): """ Register all of the filters required for the exporter. """ #Register the filters of the base class. - super(LatexExporter, self)._register_filters() + super(LatexExporter, self)._init_filters() #Add latex filters to the Jinja2 environment self.register_filter('escape_tex', filters.escape_latex) self.register_filter('highlight', filters.highlight2latex) - - def _register_transformers(self): - """ - Register all of the transformers needed for this exporter. - """ - - #Register ConvertSvgTransformer before any other transformers! - #Important because it allows the conversion of svg->png BEFORE the - #extract figure transformer acts on the data. - self.register_transformer(transformers.ConvertSvgTransformer, True) - - #Register transformers - super(LatexExporter, self)._register_transformers() - self.register_transformer(transformers.LatexTransformer, True) @property def default_config(self): c = Config({ 'GlobalConfigurable': { - 'display_data_priority' : ['latex', 'png', 'jpg', 'pdf', 'jpeg', 'text'] + 'display_data_priority' : ['latex', 'png', 'jpg', 'svg', 'jpeg', 'text'] }, 'ExtractFigureTransformer': { 'enabled':True + }, + 'Svg2PdfTransformer': { + 'enabled':True + }, + 'LatexTransformer': { + 'enabled':True } - }) c.merge(super(LatexExporter,self).default_config) return c - diff --git a/IPython/nbconvert/exporters/reveal.py b/IPython/nbconvert/exporters/reveal.py index 0d63eb1..860dfb5 100644 --- a/IPython/nbconvert/exporters/reveal.py +++ b/IPython/nbconvert/exporters/reveal.py @@ -13,7 +13,7 @@ Reveal slide show exporter. # Imports #----------------------------------------------------------------------------- -from IPython.utils.traitlets import Unicode +from IPython.utils.traitlets import Unicode, List from IPython.config import Config from .basichtml import BasicHTMLExporter @@ -35,17 +35,15 @@ class RevealExporter(BasicHTMLExporter): template_file = Unicode( 'reveal', config=True, help="Name of the template file to use") + + default_transformers = List([transformers.coalesce_streams, + transformers.ExtractFigureTransformer, + transformers.CSSHTMLHeaderTransformer, + transformers.RevealHelpTransformer], + config=True, + help="""List of transformers available by default, by name, namespace, + instance, or type.""") - def _register_transformers(self): - """ - Register all of the transformers needed for this exporter. - """ - - #Register the transformers of the base class. - super(RevealExporter, self)._register_transformers() - - #Register reveal help transformer - self.register_transformer(transformers.RevealHelpTransformer, enabled=True) @property def default_config(self): diff --git a/IPython/nbconvert/exporters/sphinx_howto.py b/IPython/nbconvert/exporters/sphinx_howto.py index 1056850..f2c606e 100644 --- a/IPython/nbconvert/exporters/sphinx_howto.py +++ b/IPython/nbconvert/exporters/sphinx_howto.py @@ -14,7 +14,7 @@ formatted for use with PDFLatex. # Imports #----------------------------------------------------------------------------- -from IPython.utils.traitlets import Unicode +from IPython.utils.traitlets import Unicode, List from IPython.config import Config # local import @@ -36,10 +36,18 @@ class SphinxHowtoExporter(LatexExporter): 'sphinx_howto', config=True, help="Name of the template file to use") - def _register_transformers(self): - - #Register the transformers of the base class. - super(SphinxHowtoExporter, self)._register_transformers() - - #Register sphinx latex transformer - self.register_transformer(transformers.SphinxTransformer, enabled=True) + default_transformers = List([transformers.Svg2PdfTransformer, + transformers.ExtractFigureTransformer, + transformers.CSSHTMLHeaderTransformer, + transformers.LatexTransformer, + transformers.SphinxTransformer], + config=True, + help="""List of transformers available by default, by name, namespace, + instance, or type.""") + + + @property + def default_config(self): + c = Config({'SphinxTransformer': {'enabled':True}}) + c.merge(super(SphinxHowtoExporter,self).default_config) + return c diff --git a/IPython/nbconvert/templates/latex/sphinx_base.tplx b/IPython/nbconvert/templates/latex/sphinx_base.tplx index 7750118..3e3cdcd 100644 --- a/IPython/nbconvert/templates/latex/sphinx_base.tplx +++ b/IPython/nbconvert/templates/latex/sphinx_base.tplx @@ -145,11 +145,11 @@ Note: For best display, use latex syntax highlighting. =)) \sloppy % Document level variables - \title{((( nb.metadata.name | escape_tex )))} - \date{((( nb.metadata._draft.date | escape_tex )))} - \release{((( nb.metadata._draft.version | escape_tex )))} - \author{((( nb.metadata._draft.author | escape_tex )))} - \renewcommand{\releasename}{((( nb.metadata._draft.release | escape_tex )))} + \title{((( resources.metadata.name | escape_tex )))} + \date{((( resources.sphinx.date | escape_tex )))} + \release{((( resources.sphinx.version | escape_tex )))} + \author{((( resources.sphinx.author | escape_tex )))} + \renewcommand{\releasename}{((( resources.sphinx.release | escape_tex )))} % TODO: Add option for the user to specify a logo for his/her export. \newcommand{\sphinxlogo}{} diff --git a/IPython/nbconvert/transformers/sphinx.py b/IPython/nbconvert/transformers/sphinx.py index b5a1b47..6f18cd0 100755 --- a/IPython/nbconvert/transformers/sphinx.py +++ b/IPython/nbconvert/transformers/sphinx.py @@ -127,9 +127,6 @@ class SphinxTransformer(ActivatableTransformer): # TODO: Add versatile method of additional notebook metadata. Include # handling of multiple files. For now use a temporay namespace, # '_draft' to signify that this needs to change. - if not "_draft" in nb.metadata: - nb.metadata._draft = {} -#TODO: Remove draft, and nb if not "sphinx" in resources: resources["sphinx"] = {} @@ -137,10 +134,10 @@ class SphinxTransformer(ActivatableTransformer): # Prompt the user for additional meta data that doesn't exist currently # but would be usefull for Sphinx. - nb.metadata._draft["author"] = self._prompt_author() - nb.metadata._draft["version"] = self._prompt_version() - nb.metadata._draft["release"] = self._prompt_release() - nb.metadata._draft["date"] = self._prompt_date() + resources["sphinx"]["author"] = self._prompt_author() + resources["sphinx"]["version"] = self._prompt_version() + resources["sphinx"]["release"] = self._prompt_release() + resources["sphinx"]["date"] = self._prompt_date() # Prompt the user for the document style. resources["sphinx"]["chapterstyle"] = self._prompt_chapter_title_style() @@ -152,15 +149,17 @@ class SphinxTransformer(ActivatableTransformer): else: # Try to use the traitlets. - nb.metadata._draft["author"] = self.author - nb.metadata._draft["version"] = self.version - nb.metadata._draft["release"] = self.release + resources["sphinx"]["author"] = self.author + resources["sphinx"]["version"] = self.version + resources["sphinx"]["release"] = self.release # Use todays date if none is provided. - if len(self.publish_date.strip()) == 0: - nb.metadata._draft["date"] = date.today().strftime("%B %d, %Y") + if self.publish_date: + resources["sphinx"]["date"] = self.publish_date + elif len(resources['metadata']['modified_date'].strip()) == 0: + resources["sphinx"]["date"] = date.today().strftime("%B %-d, %Y") else: - nb.metadata._draft["date"] = self.publish_date + resources["sphinx"]["date"] = resources['metadata']['modified_date'] # Sphinx traitlets. resources["sphinx"]["chapterstyle"] = self.chapter_style @@ -175,7 +174,7 @@ class SphinxTransformer(ActivatableTransformer): resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def() if not (self.overridetitle == None or len(self.overridetitle.strip()) == 0): - nb.metadata.name = self.overridetitle + resources['metadata']['name'] = self.overridetitle # End return nb, resources @@ -212,12 +211,16 @@ class SphinxTransformer(ActivatableTransformer): return console.input("Release Name (ie ""Rough draft""): ") - def _prompt_date(self): + def _prompt_date(self, resources): """ Prompt the user to enter a date """ - default_date = date.today().strftime("%B %d, %Y") + if resources['metadata']['modified_date']: + default_date = resources['metadata']['modified_date'] + else: + default_date = date.today().strftime("%B %-d, %Y") + user_date = console.input("Date (deafults to \"" + default_date + "\"): ") if len(user_date.strip()) == 0: user_date = default_date