diff --git a/IPython/nbconvert/__init__.py b/IPython/nbconvert/__init__.py index 121eed9..d5e7352 100755 --- a/IPython/nbconvert/__init__.py +++ b/IPython/nbconvert/__init__.py @@ -3,4 +3,5 @@ from .exporters import * import filters import transformers +import post_processors import writers diff --git a/IPython/nbconvert/exporters/__init__.py b/IPython/nbconvert/exporters/__init__.py index dca2a59..c4eb2cb 100755 --- a/IPython/nbconvert/exporters/__init__.py +++ b/IPython/nbconvert/exporters/__init__.py @@ -1,11 +1,8 @@ -from .basichtml import BasicHTMLExporter from .export import * +from .html import HTMLExporter +from .slides import SlidesExporter from .exporter import Exporter -from .fullhtml import FullHTMLExporter -from .reveal import RevealExporter from .latex import LatexExporter from .markdown import MarkdownExporter from .python import PythonExporter from .rst import RSTExporter -from .sphinx_howto import SphinxHowtoExporter -from .sphinx_manual import SphinxManualExporter diff --git a/IPython/nbconvert/exporters/export.py b/IPython/nbconvert/exporters/export.py index 83d3bcf..4413586 100755 --- a/IPython/nbconvert/exporters/export.py +++ b/IPython/nbconvert/exporters/export.py @@ -19,15 +19,12 @@ from IPython.nbformat.v3.nbbase import NotebookNode from IPython.config import Config from .exporter import Exporter -from .basichtml import BasicHTMLExporter -from .fullhtml import FullHTMLExporter +from .html import HTMLExporter +from .slides import SlidesExporter from .latex import LatexExporter from .markdown import MarkdownExporter from .python import PythonExporter -from .reveal import RevealExporter from .rst import RSTExporter -from .sphinx_howto import SphinxHowtoExporter -from .sphinx_manual import SphinxManualExporter #----------------------------------------------------------------------------- # Classes @@ -54,7 +51,10 @@ def DocDecorator(f): exporter_instance : Exporter Instance of the Exporter class used to export the document. Useful to caller because it provides a 'file_extension' property which - specifies what extension the output should be saved as.""" + specifies what extension the output should be saved as. + + WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT + """ @wraps(f) def decorator(*args, **kwargs): @@ -69,14 +69,12 @@ def DocDecorator(f): __all__ = [ 'export', - 'export_sphinx_manual', - 'export_sphinx_howto', - 'export_basic_html', - 'export_full_html', + 'export_html', + 'export_custom', + 'export_slides', 'export_latex', 'export_markdown', 'export_python', - 'export_reveal', 'export_rst', 'export_by_name', 'get_export_names', @@ -126,35 +124,27 @@ def export(exporter, nb, **kw): @DocDecorator -def export_sphinx_manual(nb, **kw): - """ - Export a notebook object to Sphinx Manual LaTeX - """ - return export(SphinxManualExporter, nb, **kw) - - -@DocDecorator -def export_sphinx_howto(nb, **kw): +def export_custom(nb, **kw): """ - Export a notebook object to Sphinx HowTo LaTeX + Export a notebook object to a custom format """ - return export(SphinxHowtoExporter, nb, **kw) + return export(Exporter, nb, **kw) @DocDecorator -def export_basic_html(nb, **kw): +def export_html(nb, **kw): """ - Export a notebook object to Basic HTML + Export a notebook object to HTML """ - return export(BasicHTMLExporter, nb, **kw) + return export(HTMLExporter, nb, **kw) @DocDecorator -def export_full_html(nb, **kw): +def export_slides(nb, **kw): """ - Export a notebook object to Full HTML + Export a notebook object to Slides """ - return export(FullHTMLExporter, nb, **kw) + return export(SlidesExporter, nb, **kw) @DocDecorator @@ -182,14 +172,6 @@ def export_python(nb, **kw): @DocDecorator -def export_reveal(nb, **kw): - """ - Export a notebook object to a Reveal.js presentation - """ - return export(RevealExporter, nb, **kw) - - -@DocDecorator def export_rst(nb, **kw): """ Export a notebook object to reStructuredText @@ -217,7 +199,10 @@ def export_by_name(format_name, nb, **kw): def get_export_names(): - "Return a list of the currently supported export targets" + """Return a list of the currently supported export targets + + WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT""" + # grab everything after 'export_' l = [x[len('export_'):] for x in __all__ if x.startswith('export_')] diff --git a/IPython/nbconvert/exporters/exporter.py b/IPython/nbconvert/exporters/exporter.py index 23e3570..450a0b1 100755 --- a/IPython/nbconvert/exporters/exporter.py +++ b/IPython/nbconvert/exporters/exporter.py @@ -25,7 +25,7 @@ import collections import datetime # other libs/dependencies -from jinja2 import Environment, FileSystemLoader, ChoiceLoader +from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound # IPython imports from IPython.config.configurable import Configurable @@ -86,7 +86,7 @@ class Exporter(Configurable): 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. - + {filters} """ @@ -94,9 +94,15 @@ class Exporter(Configurable): __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys())) - template_file = Unicode( - '', config=True, + template_file = Unicode(u'default', + config=True, help="Name of the template file to use") + def _template_file_changed(self, name, old, new): + if new=='default': + self.template_file = self.default_template + else: + self.template_file = new + default_template = Unicode(u'') file_extension = Unicode( 'txt', config=True, @@ -155,6 +161,8 @@ class Exporter(Configurable): extra_loaders : list[of Jinja Loaders] ordered list of Jinja loder to find templates. Will be tried in order before the default FileSysteme ones. + template : str (optional, kw arg) + Template to use when exporting. """ #Call the base class constructor @@ -165,6 +173,7 @@ class Exporter(Configurable): super(Exporter, self).__init__(config=c, **kw) #Init + self._init_template(**kw) self._init_environment(extra_loaders=extra_loaders) self._init_transformers() self._init_filters() @@ -189,12 +198,29 @@ class Exporter(Configurable): nb_copy = copy.deepcopy(nb) resources = self._init_resources(resources) - #Preprocess + # Preprocess nb_copy, resources = self._transform(nb_copy, resources) - #Convert - self.template = self.environment.get_template(self.template_file + self.template_extension) - output = self.template.render(nb=nb_copy, resources=resources) + # Try different template names during conversion. First try to load the + # template by name with extension added, then try loading the template + # as if the name is explicitly specified, then try the name as a + # 'flavor', and lastly just try to load the template by module name. + module_name = self.__module__.split('.')[-1] + try_names = [self.template_file + self.template_extension, + self.template_file, + module_name + '_' + self.template_file + self.template_extension, + module_name + self.template_extension] + for try_name in try_names: + try: + self.template = self.environment.get_template(try_name) + break + except TemplateNotFound: + pass + + if hasattr(self, 'template'): + output = self.template.render(nb=nb_copy, resources=resources) + else: + raise IOError('template file "%s" could not be found' % self.template_file) return output, resources @@ -329,6 +355,16 @@ class Exporter(Configurable): raise TypeError('filter') + def _init_template(self, **kw): + """ + Make sure a template name is specified. If one isn't specified, try to + build one from the information we know. + """ + self._template_file_changed('template_file', self.template_file, self.template_file) + if 'template' in kw: + self.template_file = kw['template'] + + def _init_environment(self, extra_loaders=None): """ Create the Jinja templating environment. diff --git a/IPython/nbconvert/exporters/fullhtml.py b/IPython/nbconvert/exporters/fullhtml.py deleted file mode 100644 index e0f2fcd..0000000 --- a/IPython/nbconvert/exporters/fullhtml.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Exporter for exporting full HTML documents. -""" - -#----------------------------------------------------------------------------- -# 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from IPython.utils.traitlets import Unicode - -from .basichtml import BasicHTMLExporter -from IPython.config import Config - -#----------------------------------------------------------------------------- -# Classes -#----------------------------------------------------------------------------- - -class FullHTMLExporter(BasicHTMLExporter): - """ - Exports a full HTML document. - """ - - template_file = Unicode( - 'fullhtml', config=True, - help="Name of the template file to use") - - @property - def default_config(self): - c = Config({'CSSHTMLHeaderTransformer':{'enabled':True}}) - c.merge(super(FullHTMLExporter,self).default_config) - return c diff --git a/IPython/nbconvert/exporters/basichtml.py b/IPython/nbconvert/exporters/html.py similarity index 77% rename from IPython/nbconvert/exporters/basichtml.py rename to IPython/nbconvert/exporters/html.py index e90c16f..f79193d 100644 --- a/IPython/nbconvert/exporters/basichtml.py +++ b/IPython/nbconvert/exporters/html.py @@ -17,6 +17,7 @@ Exporter that exports Basic HTML. from IPython.utils.traitlets import Unicode, List from IPython.nbconvert import transformers +from IPython.config import Config from .exporter import Exporter @@ -24,7 +25,7 @@ from .exporter import Exporter # Classes #----------------------------------------------------------------------------- -class BasicHTMLExporter(Exporter): +class HTMLExporter(Exporter): """ Exports a basic HTML document. This exporter assists with the export of HTML. Inherit from it if you are writing your own HTML template and need @@ -37,6 +38,15 @@ class BasicHTMLExporter(Exporter): help="Extension of the file that should be written to disk" ) - template_file = Unicode( - 'basichtml', config=True, - help="Name of the template file to use") + default_template = Unicode('full', config=True, help="""Flavor of the data + format to use. I.E. 'full' or 'basic'""") + + @property + def default_config(self): + c = Config({ + 'CSSHTMLHeaderTransformer':{ + 'enabled':True + } + }) + c.merge(super(HTMLExporter,self).default_config) + return c diff --git a/IPython/nbconvert/exporters/latex.py b/IPython/nbconvert/exporters/latex.py index 66751ce..453f95b 100755 --- a/IPython/nbconvert/exporters/latex.py +++ b/IPython/nbconvert/exporters/latex.py @@ -44,9 +44,8 @@ class LatexExporter(Exporter): 'tex', config=True, help="Extension of the file that should be written to disk") - template_file = Unicode( - 'base', config=True, - help="Name of the template file to use") + default_template = Unicode('article', config=True, help="""Template of the + data format to use. I.E. 'full' or 'basic'""") #Latex constants default_template_path = Unicode( @@ -68,6 +67,7 @@ class LatexExporter(Exporter): #Extension that the template files use. template_extension = Unicode(".tplx", config=True) + @property def default_config(self): c = Config({ @@ -82,6 +82,9 @@ class LatexExporter(Exporter): }, 'LatexTransformer': { 'enabled':True + }, + 'SphinxTransformer': { + 'enabled':True } }) c.merge(super(LatexExporter,self).default_config) diff --git a/IPython/nbconvert/exporters/markdown.py b/IPython/nbconvert/exporters/markdown.py index 7c38f43..160fd67 100644 --- a/IPython/nbconvert/exporters/markdown.py +++ b/IPython/nbconvert/exporters/markdown.py @@ -29,7 +29,3 @@ class MarkdownExporter(Exporter): file_extension = Unicode( 'md', config=True, help="Extension of the file that should be written to disk") - - template_file = Unicode( - 'markdown', config=True, - help="Name of the template file to use") diff --git a/IPython/nbconvert/exporters/python.py b/IPython/nbconvert/exporters/python.py index b6bae64..9fe2a94 100644 --- a/IPython/nbconvert/exporters/python.py +++ b/IPython/nbconvert/exporters/python.py @@ -29,7 +29,3 @@ class PythonExporter(Exporter): file_extension = Unicode( 'py', config=True, help="Extension of the file that should be written to disk") - - template_file = Unicode( - 'python', config=True, - help="Name of the template file to use") diff --git a/IPython/nbconvert/exporters/rst.py b/IPython/nbconvert/exporters/rst.py index 1388a63..0204e13 100644 --- a/IPython/nbconvert/exporters/rst.py +++ b/IPython/nbconvert/exporters/rst.py @@ -31,10 +31,6 @@ class RSTExporter(Exporter): 'rst', config=True, help="Extension of the file that should be written to disk") - template_file = Unicode( - 'rst', config=True, - help="Name of the template file to use") - @property def default_config(self): c = Config({'ExtractOutputTransformer':{'enabled':True}}) diff --git a/IPython/nbconvert/exporters/reveal.py b/IPython/nbconvert/exporters/slides.py similarity index 73% rename from IPython/nbconvert/exporters/reveal.py rename to IPython/nbconvert/exporters/slides.py index ec87bcf..50e7f99 100644 --- a/IPython/nbconvert/exporters/reveal.py +++ b/IPython/nbconvert/exporters/slides.py @@ -1,6 +1,7 @@ """ -Reveal slide show exporter. +Contains slide show exporter """ + #----------------------------------------------------------------------------- # Copyright (c) 2013, the IPython Development Team. # @@ -13,29 +14,29 @@ Reveal slide show exporter. # Imports #----------------------------------------------------------------------------- -from IPython.utils.traitlets import Unicode, List -from IPython.config import Config +from IPython.utils.traitlets import Unicode -from .basichtml import BasicHTMLExporter from IPython.nbconvert import transformers +from IPython.config import Config + +from .exporter import Exporter #----------------------------------------------------------------------------- # Classes #----------------------------------------------------------------------------- -class RevealExporter(BasicHTMLExporter): +class SlidesExporter(Exporter): """ - Exports a Reveal slide show (.HTML) which may be rendered in a web browser. + Exports slides """ file_extension = Unicode( - 'reveal.html', config=True, - help="Extension of the file that should be written to disk") - - template_file = Unicode( - 'reveal', config=True, - help="Name of the template file to use") + 'slides.html', config=True, + help="Extension of the file that should be written to disk" + ) + default_template = Unicode('reveal', config=True, help="""Template of the + data format to use. I.E. 'reveal'""") @property def default_config(self): @@ -47,5 +48,5 @@ class RevealExporter(BasicHTMLExporter): 'enabled':True, }, }) - c.merge(super(RevealExporter,self).default_config) + c.merge(super(SlidesExporter,self).default_config) return c diff --git a/IPython/nbconvert/exporters/sphinx_howto.py b/IPython/nbconvert/exporters/sphinx_howto.py deleted file mode 100644 index b771978..0000000 --- a/IPython/nbconvert/exporters/sphinx_howto.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Exporter for exporting notebooks to Sphinx 'HowTo' style latex. Latex -formatted for use with PDFLatex. -""" -#----------------------------------------------------------------------------- -# 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from IPython.utils.traitlets import Unicode, List -from IPython.config import Config - -# local import -from .latex import LatexExporter - -from IPython.nbconvert import transformers - -#----------------------------------------------------------------------------- -# Classes -#----------------------------------------------------------------------------- - -class SphinxHowtoExporter(LatexExporter): - """ - Exports Sphinx "HowTo" LaTeX documents. The Sphinx "HowTo" exporter - produces short document format latex for use with PDFLatex. - """ - - template_file = Unicode( - 'sphinx_howto', config=True, - help="Name of the template file to use") - - - @property - def default_config(self): - c = Config({'SphinxTransformer': {'enabled':True}}) - c.merge(super(SphinxHowtoExporter,self).default_config) - return c diff --git a/IPython/nbconvert/exporters/tests/test_fullhtml.py b/IPython/nbconvert/exporters/tests/test_html.py similarity index 60% rename from IPython/nbconvert/exporters/tests/test_fullhtml.py rename to IPython/nbconvert/exporters/tests/test_html.py index 88a2988..f5df23c 100644 --- a/IPython/nbconvert/exporters/tests/test_fullhtml.py +++ b/IPython/nbconvert/exporters/tests/test_html.py @@ -1,5 +1,5 @@ """ -Module with tests for fullhtml.py +Module with tests for html.py """ #----------------------------------------------------------------------------- @@ -15,26 +15,45 @@ Module with tests for fullhtml.py #----------------------------------------------------------------------------- from .base import ExportersTestsBase -from ..fullhtml import FullHTMLExporter +from ..html import HTMLExporter from IPython.testing.decorators import onlyif_cmds_exist #----------------------------------------------------------------------------- # Class #----------------------------------------------------------------------------- -class TestFullHTMLExporter(ExportersTestsBase): - """Contains test functions for fullhtml.py""" +class TestHTMLExporter(ExportersTestsBase): + """Contains test functions for html.py""" def test_constructor(self): """ - Can a FullHTMLExporter be constructed? + Can a HTMLExporter be constructed? """ - FullHTMLExporter() + HTMLExporter() + @onlyif_cmds_exist('pandoc') def test_export(self): """ - Can a FullHTMLExporter export something? + Can a HTMLExporter export something? + """ + (output, resources) = HTMLExporter().from_filename(self._get_notebook()) + assert len(output) > 0 + + + @onlyif_cmds_exist('pandoc') + def test_export_basic(self): + """ + Can a HTMLExporter export using the 'basic' template? + """ + (output, resources) = HTMLExporter(template='basic').from_filename(self._get_notebook()) + assert len(output) > 0 + + + @onlyif_cmds_exist('pandoc') + def test_export_full(self): + """ + Can a HTMLExporter export using the 'full' template? """ - (output, resources) = FullHTMLExporter().from_filename(self._get_notebook()) + (output, resources) = HTMLExporter(template='full').from_filename(self._get_notebook()) assert len(output) > 0 diff --git a/IPython/nbconvert/exporters/tests/test_latex.py b/IPython/nbconvert/exporters/tests/test_latex.py index e9f4061..b692eb7 100644 --- a/IPython/nbconvert/exporters/tests/test_latex.py +++ b/IPython/nbconvert/exporters/tests/test_latex.py @@ -39,3 +39,30 @@ class TestLatexExporter(ExportersTestsBase): """ (output, resources) = LatexExporter().from_filename(self._get_notebook()) assert len(output) > 0 + + + @onlyif_cmds_exist('pandoc') + def test_export_book(self): + """ + Can a LatexExporter export using 'book' template? + """ + (output, resources) = LatexExporter(template='book').from_filename(self._get_notebook()) + assert len(output) > 0 + + + @onlyif_cmds_exist('pandoc') + def test_export_basic(self): + """ + Can a LatexExporter export using 'basic' template? + """ + (output, resources) = LatexExporter(template='basic').from_filename(self._get_notebook()) + assert len(output) > 0 + + + @onlyif_cmds_exist('pandoc') + def test_export_article(self): + """ + Can a LatexExporter export using 'article' template? + """ + (output, resources) = LatexExporter(template='article').from_filename(self._get_notebook()) + assert len(output) > 0 \ No newline at end of file diff --git a/IPython/nbconvert/exporters/tests/test_reveal.py b/IPython/nbconvert/exporters/tests/test_reveal.py deleted file mode 100644 index 822e90c..0000000 --- a/IPython/nbconvert/exporters/tests/test_reveal.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Module with tests for reveal.py -""" - -#----------------------------------------------------------------------------- -# 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from .base import ExportersTestsBase -from ..reveal import RevealExporter -from IPython.testing.decorators import onlyif_cmds_exist - -#----------------------------------------------------------------------------- -# Class -#----------------------------------------------------------------------------- - -class TestRevealExporter(ExportersTestsBase): - """Contains test functions for reveal.py""" - - def test_constructor(self): - """ - Can a RevealExporter be constructed? - """ - RevealExporter() - - - @onlyif_cmds_exist('pandoc') - def test_export(self): - """ - Can a RevealExporter export something? - """ - (output, resources) = RevealExporter().from_filename(self._get_notebook()) - assert len(output) > 0 diff --git a/IPython/nbconvert/exporters/tests/test_basichtml.py b/IPython/nbconvert/exporters/tests/test_slides.py similarity index 64% rename from IPython/nbconvert/exporters/tests/test_basichtml.py rename to IPython/nbconvert/exporters/tests/test_slides.py index a02d713..06443a6 100644 --- a/IPython/nbconvert/exporters/tests/test_basichtml.py +++ b/IPython/nbconvert/exporters/tests/test_slides.py @@ -1,5 +1,5 @@ """ -Module with tests for basichtml.py +Module with tests for slides.py """ #----------------------------------------------------------------------------- @@ -15,26 +15,33 @@ Module with tests for basichtml.py #----------------------------------------------------------------------------- from .base import ExportersTestsBase -from ..basichtml import BasicHTMLExporter -from IPython.testing.decorators import onlyif_cmds_exist +from ..slides import SlidesExporter #----------------------------------------------------------------------------- # Class #----------------------------------------------------------------------------- -class TestBasicHTMLExporter(ExportersTestsBase): - """Contains test functions for basichtml.py""" +class TestSlidesExporter(ExportersTestsBase): + """Contains test functions for slides.py""" def test_constructor(self): """ - Can a BasicHTMLExporter be constructed? + Can a SlidesExporter be constructed? """ - BasicHTMLExporter() + SlidesExporter() + - @onlyif_cmds_exist('pandoc') def test_export(self): """ - Can a BasicHTMLExporter export something? + Can a SlidesExporter export something? + """ + (output, resources) = SlidesExporter().from_filename(self._get_notebook()) + assert len(output) > 0 + + + def test_export_reveal(self): + """ + Can a SlidesExporter export using the 'reveal' template? """ - (output, resources) = BasicHTMLExporter().from_filename(self._get_notebook()) + (output, resources) = SlidesExporter(template='reveal').from_filename(self._get_notebook()) assert len(output) > 0 diff --git a/IPython/nbconvert/exporters/tests/test_sphinx_howto.py b/IPython/nbconvert/exporters/tests/test_sphinx_howto.py deleted file mode 100644 index 5004155..0000000 --- a/IPython/nbconvert/exporters/tests/test_sphinx_howto.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Module with tests for sphinx_howto.py -""" - -#----------------------------------------------------------------------------- -# 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from .base import ExportersTestsBase -from ..sphinx_howto import SphinxHowtoExporter -from IPython.testing.decorators import onlyif_cmds_exist - -#----------------------------------------------------------------------------- -# Class -#----------------------------------------------------------------------------- - -class TestSphinxHowtoExporter(ExportersTestsBase): - """Contains test functions for sphinx_howto.py""" - - def test_constructor(self): - """ - Can a SphinxHowtoExporter be constructed? - """ - SphinxHowtoExporter() - - - @onlyif_cmds_exist('pandoc') - def test_export(self): - """ - Can a SphinxHowtoExporter export something? - """ - (output, resources) = SphinxHowtoExporter().from_filename(self._get_notebook()) - assert len(output) > 0 diff --git a/IPython/nbconvert/exporters/tests/test_sphinx_manual.py b/IPython/nbconvert/exporters/tests/test_sphinx_manual.py deleted file mode 100644 index 3f78b4c..0000000 --- a/IPython/nbconvert/exporters/tests/test_sphinx_manual.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Module with tests for sphinx_manual.py -""" - -#----------------------------------------------------------------------------- -# 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from .base import ExportersTestsBase -from ..sphinx_manual import SphinxManualExporter -from IPython.testing.decorators import onlyif_cmds_exist - -#----------------------------------------------------------------------------- -# Class -#----------------------------------------------------------------------------- - -class TestSphinxManualExporter(ExportersTestsBase): - """Contains test functions for sphinx_manual.py""" - - def test_constructor(self): - """ - Can a SphinxManualExporter be constructed? - """ - SphinxManualExporter() - - - @onlyif_cmds_exist('pandoc') - def test_export(self): - """ - Can a SphinxManualExporter export something? - """ - (output, resources) = SphinxManualExporter().from_filename(self._get_notebook()) - assert len(output) > 0 diff --git a/IPython/nbconvert/nbconvertapp.py b/IPython/nbconvert/nbconvertapp.py index cf0738a..92e8791 100755 --- a/IPython/nbconvert/nbconvertapp.py +++ b/IPython/nbconvert/nbconvertapp.py @@ -30,7 +30,7 @@ from IPython.utils.traitlets import ( from IPython.utils.importstring import import_item from .exporters.export import export_by_name, get_export_names, ExporterNameError -from IPython.nbconvert import exporters, transformers, writers +from IPython.nbconvert import exporters, transformers, writers, post_processors from .utils.base import NbConvertBase from .utils.exceptions import ConversionException @@ -38,12 +38,27 @@ from .utils.exceptions import ConversionException #Classes and functions #----------------------------------------------------------------------------- +class DottedOrNone(DottedObjectName): + """ + A string holding a valid dotted object name in Python, such as A.b3._c + Also allows for None type.""" + + default_value = u'' + + def validate(self, obj, value): + if value is not None and len(value) > 0: + return super(DottedOrNone, self).validate(obj, value) + else: + return value + nbconvert_aliases = {} nbconvert_aliases.update(base_aliases) nbconvert_aliases.update({ - 'format' : 'NbConvertApp.export_format', + 'to' : 'NbConvertApp.export_format', + 'template' : 'Exporter.template_file', 'notebooks' : 'NbConvertApp.notebooks', 'writer' : 'NbConvertApp.writer_class', + 'post': 'NbConvertApp.post_processor_class' }) nbconvert_flags = {} @@ -74,7 +89,9 @@ class NbConvertApp(BaseIPythonApplication): description = Unicode( u"""This application is used to convert notebook files (*.ipynb) - to various other formats.""") + to various other formats. + + WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""") examples = Unicode(u""" The simplest way to use nbconvert is @@ -83,14 +100,24 @@ class NbConvertApp(BaseIPythonApplication): which will convert mynotebook.ipynb to the default format (probably HTML). - You can specify the export format with `--format`. + You can specify the export format with `--to`. Options include {0} - > ipython nbconvert --format latex mynotebook.ipnynb + > ipython nbconvert --to latex mynotebook.ipnynb + + Both HTML and LaTeX support multiple output templates. LaTeX includes + 'basic', 'book', and 'article'. HTML includes 'basic' and 'full'. You + can specify the flavor of the format used. + + > ipython nbconvert --to html --template basic mynotebook.ipynb You can also pipe the output to stdout, rather than a file > ipython nbconvert mynotebook.ipynb --stdout + + A post-processor can be used to compile a PDF + + > ipython nbconvert mynotebook.ipynb --to latex --post PDF Multiple notebooks can be given at the command line in a couple of different ways: @@ -104,6 +131,7 @@ class NbConvertApp(BaseIPythonApplication): > ipython nbconvert --config mycfg.py """.format(get_export_names())) + # Writer specific variables writer = Instance('IPython.nbconvert.writers.base.WriterBase', help="""Instance of the writer class used to write the @@ -121,10 +149,27 @@ class NbConvertApp(BaseIPythonApplication): new = self.writer_aliases[new] self.writer_factory = import_item(new) + # Post-processor specific variables + post_processor = Instance('IPython.nbconvert.post_processors.base.PostProcessorBase', + help="""Instance of the PostProcessor class used to write the + results of the conversion.""") + + post_processor_class = DottedOrNone(config=True, + help="""PostProcessor class used to write the + results of the conversion""") + post_processor_aliases = {'PDF': 'IPython.nbconvert.post_processors.pdf.PDFPostProcessor'} + post_processor_factory = Type() + + def _post_processor_class_changed(self, name, old, new): + if new in self.post_processor_aliases: + new = self.post_processor_aliases[new] + if new: + self.post_processor_factory = import_item(new) + # Other configurable variables export_format = CaselessStrEnum(get_export_names(), - default_value="full_html", + default_value="html", config=True, help="""The export format to be used.""" ) @@ -140,6 +185,8 @@ class NbConvertApp(BaseIPythonApplication): self.init_syspath() self.init_notebooks() self.init_writer() + self.init_post_processor() + def init_syspath(self): @@ -184,6 +231,15 @@ class NbConvertApp(BaseIPythonApplication): self._writer_class_changed(None, self.writer_class, self.writer_class) self.writer = self.writer_factory(parent=self) + def init_post_processor(self): + """ + Initialize the post_processor (which is stateless) + """ + self._post_processor_class_changed(None, self.post_processor_class, + self.post_processor_class) + if self.post_processor_factory: + self.post_processor = self.post_processor_factory(parent=self) + def start(self): """ Ran after initialization completed @@ -225,7 +281,11 @@ class NbConvertApp(BaseIPythonApplication): file=sys.stderr) self.exit(1) else: - self.writer.write(output, resources, notebook_name=notebook_name) + write_resultes = self.writer.write(output, resources, notebook_name=notebook_name) + + #Post-process if post processor has been defined. + if hasattr(self, 'post_processor') and self.post_processor: + self.post_processor(write_resultes) conversion_success += 1 # If nothing was converted successfully, help the user. diff --git a/IPython/nbconvert/post_processors/__init__.py b/IPython/nbconvert/post_processors/__init__.py new file mode 100644 index 0000000..72c4819 --- /dev/null +++ b/IPython/nbconvert/post_processors/__init__.py @@ -0,0 +1,2 @@ +from .base import PostProcessorBase +from .pdf import PDFPostProcessor diff --git a/IPython/nbconvert/exporters/sphinx_manual.py b/IPython/nbconvert/post_processors/base.py similarity index 50% rename from IPython/nbconvert/exporters/sphinx_manual.py rename to IPython/nbconvert/post_processors/base.py index 6dd6896..4f709b3 100644 --- a/IPython/nbconvert/exporters/sphinx_manual.py +++ b/IPython/nbconvert/post_processors/base.py @@ -1,34 +1,35 @@ """ -Exporter for exporting notebooks to Sphinx 'Manual' style latex. Latex -formatted for use with PDFLatex. +Basic post processor """ #----------------------------------------------------------------------------- -# Copyright (c) 2013, the IPython Development Team. +#Copyright (c) 2013, the IPython Development Team. # -# Distributed under the terms of the Modified BSD License. +#Distributed under the terms of the Modified BSD License. # -# The full license is in the file COPYING.txt, distributed with this software. +#The full license is in the file COPYING.txt, distributed with this software. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- -from IPython.utils.traitlets import Unicode +from ..utils.base import NbConvertBase -from .sphinx_howto import SphinxHowtoExporter #----------------------------------------------------------------------------- # Classes #----------------------------------------------------------------------------- +class PostProcessorBase(NbConvertBase): -class SphinxManualExporter(SphinxHowtoExporter): - """ - Exports Sphinx "Manual" LaTeX documents. The Sphinx "Manual" exporter - produces book like latex output for use with PDFLatex. - """ - - template_file = Unicode( - 'sphinx_manual', config=True, - help="Name of the template file to use") - \ No newline at end of file + def __call__(self, input): + """ + See def call() ... + """ + self.call(input) + + + def call(self, input): + """ + Post-process output from a writer. + """ + raise NotImplementedError('call') diff --git a/IPython/nbconvert/post_processors/pdf.py b/IPython/nbconvert/post_processors/pdf.py new file mode 100644 index 0000000..9879369 --- /dev/null +++ b/IPython/nbconvert/post_processors/pdf.py @@ -0,0 +1,51 @@ +""" +Contains writer for writing nbconvert output to PDF. +""" +#----------------------------------------------------------------------------- +#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. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import subprocess +import os + +from IPython.utils.traitlets import Integer, Unicode, Bool + +from .base import PostProcessorBase + +#----------------------------------------------------------------------------- +# Classes +#----------------------------------------------------------------------------- +class PDFPostProcessor(PostProcessorBase): + """Writer designed to write to PDF files""" + + iteration_count = Integer(3, config=True, help=""" + How many times pdflatex will be called. + """) + + compiler = Unicode(u'pdflatex {0}', config=True, help=""" + Shell command used to compile PDF.""") + + verbose = Bool(False, config=True, help=""" + Whether or not to display the output of the compile call. + """) + + def call(self, input): + """ + Consume and write Jinja output a PDF. + See files.py for more... + """ + command = self.compiler.format(input) + for index in range(self.iteration_count): + if self.verbose: + subprocess.Popen(command, shell=True) + else: + with open(os.devnull, 'wb') as null: + subprocess.Popen(command, shell=True, stdout=null) diff --git a/IPython/nbconvert/templates/basichtml.tpl b/IPython/nbconvert/templates/html_basic.tpl similarity index 100% rename from IPython/nbconvert/templates/basichtml.tpl rename to IPython/nbconvert/templates/html_basic.tpl diff --git a/IPython/nbconvert/templates/fullhtml.tpl b/IPython/nbconvert/templates/html_full.tpl similarity index 98% rename from IPython/nbconvert/templates/fullhtml.tpl rename to IPython/nbconvert/templates/html_full.tpl index b13512c..07f1c53 100644 --- a/IPython/nbconvert/templates/fullhtml.tpl +++ b/IPython/nbconvert/templates/html_full.tpl @@ -1,4 +1,4 @@ -{%- extends 'basichtml.tpl' -%} +{%- extends 'html_basic.tpl' -%} {%- block header -%} diff --git a/IPython/nbconvert/templates/latex/sphinx_howto.tplx b/IPython/nbconvert/templates/latex/latex_article.tplx similarity index 88% rename from IPython/nbconvert/templates/latex/sphinx_howto.tplx rename to IPython/nbconvert/templates/latex/latex_article.tplx index b82f855..3fbccce 100644 --- a/IPython/nbconvert/templates/latex/sphinx_howto.tplx +++ b/IPython/nbconvert/templates/latex/latex_article.tplx @@ -4,11 +4,11 @@ Purpose: Allow export of PDF friendly Latex inspired by Sphinx HowTo document style. Most of the is derived directly from Sphinx source. - Inheritance: null>display_priority>latex_base->latex_sphinx_base + Inheritance: null>display_priority>sphinx ==========================================================================)) -((*- extends 'sphinx_base.tplx' -*)) +((*- extends 'sphinx.tplx' -*)) ((* set parentdocumentclass = 'article' *)) ((* set documentclass = 'howto' *)) diff --git a/IPython/nbconvert/templates/latex/base.tplx b/IPython/nbconvert/templates/latex/latex_basic.tplx similarity index 90% rename from IPython/nbconvert/templates/latex/base.tplx rename to IPython/nbconvert/templates/latex/latex_basic.tplx index f04bc20..81412db 100644 --- a/IPython/nbconvert/templates/latex/base.tplx +++ b/IPython/nbconvert/templates/latex/latex_basic.tplx @@ -1,5 +1,7 @@ ((*- extends 'display_priority.tplx' -*)) +\nonstopmode + ((* block in_prompt *))((* endblock in_prompt *)) ((* block output_prompt *))((* endblock output_prompt *)) diff --git a/IPython/nbconvert/templates/latex/sphinx_manual.tplx b/IPython/nbconvert/templates/latex/latex_book.tplx similarity index 86% rename from IPython/nbconvert/templates/latex/sphinx_manual.tplx rename to IPython/nbconvert/templates/latex/latex_book.tplx index ddb04b4..0f51a7e 100644 --- a/IPython/nbconvert/templates/latex/sphinx_manual.tplx +++ b/IPython/nbconvert/templates/latex/latex_book.tplx @@ -4,11 +4,11 @@ Purpose: Allow export of PDF friendly Latex inspired by Sphinx Manual document style. Most of the is derived directly from Sphinx source. - Inheritance: null>display_priority>latex_base->latex_sphinx_base + Inheritance: null>display_priority>sphinx ==========================================================================)) -((*- extends 'sphinx_base.tplx' -*)) +((*- extends 'sphinx.tplx' -*)) ((* set parentdocumentclass = 'report' *)) ((* set documentclass = 'manual' *)) diff --git a/IPython/nbconvert/templates/latex/sphinx_base.tplx b/IPython/nbconvert/templates/latex/sphinx.tplx similarity index 95% rename from IPython/nbconvert/templates/latex/sphinx_base.tplx rename to IPython/nbconvert/templates/latex/sphinx.tplx index 1fd248b..6df9058 100644 --- a/IPython/nbconvert/templates/latex/sphinx_base.tplx +++ b/IPython/nbconvert/templates/latex/sphinx.tplx @@ -9,6 +9,8 @@ Note: For best display, use latex syntax highlighting. =)) ((*- extends 'display_priority.tplx' -*)) +\nonstopmode + %============================================================================== % Declarations %============================================================================== diff --git a/IPython/nbconvert/templates/reveal_internals/reveal_cells.tpl b/IPython/nbconvert/templates/reveal_internals/reveal_cells.tpl index 5f84a41..b0c7238 100644 --- a/IPython/nbconvert/templates/reveal_internals/reveal_cells.tpl +++ b/IPython/nbconvert/templates/reveal_internals/reveal_cells.tpl @@ -1,4 +1,4 @@ -{%- extends 'basichtml.tpl' -%} +{%- extends 'html_basic.tpl' -%} diff --git a/IPython/nbconvert/templates/reveal.tpl b/IPython/nbconvert/templates/slides_reveal.tpl similarity index 100% rename from IPython/nbconvert/templates/reveal.tpl rename to IPython/nbconvert/templates/slides_reveal.tpl diff --git a/IPython/nbconvert/tests/base.py b/IPython/nbconvert/tests/base.py index 74fa04a..0955121 100644 --- a/IPython/nbconvert/tests/base.py +++ b/IPython/nbconvert/tests/base.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Contains base test class for nbconvert """ diff --git a/IPython/nbconvert/tests/test_nbconvertapp.py b/IPython/nbconvert/tests/test_nbconvertapp.py index 2e83757..355923e 100644 --- a/IPython/nbconvert/tests/test_nbconvertapp.py +++ b/IPython/nbconvert/tests/test_nbconvertapp.py @@ -17,6 +17,7 @@ import os from .base import TestsBase from IPython.utils import py3compat +from IPython.testing import decorators as dec #----------------------------------------------------------------------------- @@ -52,7 +53,7 @@ class TestNbConvertApp(TestsBase): """ with self.create_temp_cwd(['notebook*.ipynb']): assert not 'error' in self.call([IPYTHON, 'nbconvert', - '--format="python"', '--notebooks=["*.ipynb"]']).lower() + '--to="python"', '--notebooks=["*.ipynb"]']).lower() assert os.path.isfile('notebook1.py') assert os.path.isfile('notebook2.py') @@ -63,7 +64,7 @@ class TestNbConvertApp(TestsBase): """ with self.create_temp_cwd() as cwd: self.copy_files_to(['notebook*.ipynb'], 'subdir/') - assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"', + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"', '--notebooks=["%s"]' % os.path.join('subdir', '*.ipynb')]).lower() assert os.path.isfile('notebook1.py') assert os.path.isfile('notebook2.py') @@ -74,18 +75,43 @@ class TestNbConvertApp(TestsBase): Do explicit notebook names work? """ with self.create_temp_cwd(['notebook*.ipynb']): - assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"', + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"', '--notebooks=["notebook2.ipynb"]']).lower() assert not os.path.isfile('notebook1.py') assert os.path.isfile('notebook2.py') + @dec.onlyif_cmds_exist('pdflatex') + def test_post_processor(self): + """ + Do post processors work? + """ + with self.create_temp_cwd(['notebook1.ipynb']): + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="latex"', + 'notebook1', '--post="PDF"', '--PDFPostProcessor.verbose=True']).lower() + assert os.path.isfile('notebook1.tex') + print("\n\n\t" + "\n\t".join([f for f in os.listdir('.') if os.path.isfile(f)]) + "\n\n") + assert os.path.isfile('notebook1.pdf') + + + def test_template(self): + """ + Do export templates work? + """ + with self.create_temp_cwd(['notebook2.ipynb']): + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to=slides', + '--notebooks=["notebook2.ipynb"]', '--template=reveal']).lower() + assert os.path.isfile('notebook2.slides.html') + with open('notebook2.slides.html') as f: + assert '/reveal.css' in f.read() + + def test_glob_explicit(self): """ Can a search pattern be used along with matching explicit notebook names? """ with self.create_temp_cwd(['notebook*.ipynb']): - assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"', + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"', '--notebooks=["*.ipynb", "notebook1.ipynb", "notebook2.ipynb"]']).lower() assert os.path.isfile('notebook1.py') assert os.path.isfile('notebook2.py') @@ -96,7 +122,7 @@ class TestNbConvertApp(TestsBase): Can explicit notebook names be used and then a matching search pattern? """ with self.create_temp_cwd(['notebook*.ipynb']): - assert not 'error' in self.call([IPYTHON, 'nbconvert', '--format="python"', + assert not 'error' in self.call([IPYTHON, 'nbconvert', '--to="python"', '--notebooks=["notebook1.ipynb", "notebook2.ipynb", "*.ipynb"]']).lower() assert os.path.isfile('notebook1.py') assert os.path.isfile('notebook2.py') diff --git a/IPython/nbconvert/writers/__init__.py b/IPython/nbconvert/writers/__init__.py index f0bc939..2b678f2 100644 --- a/IPython/nbconvert/writers/__init__.py +++ b/IPython/nbconvert/writers/__init__.py @@ -1,2 +1,3 @@ from .files import FilesWriter from .stdout import StdoutWriter +from .base import WriterBase diff --git a/IPython/nbconvert/writers/base.py b/IPython/nbconvert/writers/base.py index 17819df..914e9c4 100644 --- a/IPython/nbconvert/writers/base.py +++ b/IPython/nbconvert/writers/base.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Contains writer base class. """ diff --git a/IPython/nbconvert/writers/debug.py b/IPython/nbconvert/writers/debug.py index 7989a23..51d524d 100644 --- a/IPython/nbconvert/writers/debug.py +++ b/IPython/nbconvert/writers/debug.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Contains debug writer. """ diff --git a/IPython/nbconvert/writers/files.py b/IPython/nbconvert/writers/files.py index f6e1da5..203f460 100644 --- a/IPython/nbconvert/writers/files.py +++ b/IPython/nbconvert/writers/files.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Contains writer for writing nbconvert output to filesystem. """ @@ -100,3 +99,4 @@ class FilesWriter(WriterBase): # Write conversion results. with io.open(dest, 'w') as f: f.write(output) + return dest \ No newline at end of file diff --git a/IPython/nbconvert/writers/stdout.py b/IPython/nbconvert/writers/stdout.py index 4dd2bb4..d91fcee 100644 --- a/IPython/nbconvert/writers/stdout.py +++ b/IPython/nbconvert/writers/stdout.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Contains Stdout writer """