diff --git a/converters/sphinx_transformer.py b/converters/sphinx_transformer.py new file mode 100644 index 0000000..ba7893a --- /dev/null +++ b/converters/sphinx_transformer.py @@ -0,0 +1,182 @@ +""" +Module that allows custom Sphinx parameters to be set on the notebook and +on the 'other' object passed into Jinja. +""" + +# Used to find Sphinx package location +import sphinx +import os.path + +# Used to determine python version +import sys + +# Used to set the default date to today's date +from datetime import date + +# Configurable traitlets +from IPython.utils.traitlets import Unicode, Bool + +# Needed to override transformer +from converters.transformers import (ConfigurableTransformers) + +class SphinxTransformer(ConfigurableTransformers): + """ + Sphinx utility transformer. + + This transformer is used to set variables needed by the latex to build + Sphinx stylized templates. + """ + + interactive = Bool(True, config=True, help=""" + Allows you to define whether or not the Sphinx exporter will prompt + you for input during the conversion process. If this is set to false, + the author, version, release, date, and chapterstyle traits should + be set. + """) + + author = Unicode("Unknown Author", config=True, help="Author name") + + version = Unicode("", config=True, help="""Version number + You can leave this blank if you do not want to render a version number. + Example: "1.0.0" + """) + + release = Unicode("", config=True, help="""Release name + You can leave this blank if you do not want to render a release name. + Example: "Rough Draft" + """) + + publishdate = Unicode("", config=True, help="""Publish date + This is the date to render on the document as the publish date. + Leave this blank to default to todays date. + Example: "June 12, 1990" + """) + + chapterstyle = Unicode("Bjarne", config=True, help="""Sphinx chapter style + This is the style to use for the chapter headers in the document. + You may choose one of the following: + "Bjarne" (default) + "Lenny" + "Glenn" + "Conny" + "Rejne" + "Sonny" (used for international documents) + """) + + + def __call__(self, nb, other): + """ + Sphinx transformation to apply on each notebook. + + Since we are not interested in any additional manipulation on a cell + by cell basis, we do not call the base implementation. + """ + + if self.interactive: + + # Prompt the user for additional meta data that doesn't exist currently + # but would be usefull for Sphinx. + nb.metadata["author"] = self._prompt_author() + nb.metadata["version"] = self._prompt_version() + nb.metadata["release"] = self._prompt_release() + nb.metadata["date"] = self._prompt_date() + + # Prompt the user for the document style. + other["sphinx_chapterstyle"] = self._prompt_chapter_title_style() + else: + + # Try to use the traitlets. + nb.metadata["author"] = self.author + nb.metadata["version"] = self.version + nb.metadata["release"] = self.release + + if len(self.publishdate.strip()) == 0: + nb.metadata["date"] = date.today().strftime("%B %-d, %Y") + else: + nb.metadata["date"] = self.publishdate + + other["sphinx_chapterstyle"] = self.chapterstyle + + # Find and pass in the path to the Sphinx dependencies. + other["sphinx_texinputs"] = os.path.abspath(sphinx.__file__ + "/../texinputs") + + # End + return nb, other + + def _prompt_author(self): + return self._input("Author name: ") + + def _prompt_version(self): + return self._input("Version (ie ""1.0.0""): ") + + def _prompt_release(self): + return self._input("Release Name (ie ""Rough draft""): ") + + def _prompt_date(self): + default_date = date.today().strftime("%B %-d, %Y") + user_date = self._input("Date (deafults to \"" + default_date + "\"): ") + if len(user_date.strip()) == 0: + user_date = default_date + return user_date + + def _prompt_chapter_title_style(self): + + # Dictionary of available Sphinx styles + styles = {1: "Bjarne", + 2: "Lenny", + 3: "Glenn", + 4: "Conny", + 5: "Rejne", + 6: "Sonny"} + default_style = 1 + + # Build the menu that will be displayed to the user with + # all of the options available. + style_prompt = "" + for key, value in styles.iteritems(): + style_prompt += "%d %s" % (key, value) + if key == default_style: + style_prompt += " (default)" + elif value == "Sonny": + style_prompt += " (for international documents)" + style_prompt += "\n" + + # Continue to ask the user for a style until an appropriate + # one is specified. + response = -1 + while (0 > response or response > 6): + try: + text_response = self._input(style_prompt) + + # Use default option if no input. + if len(text_response.strip()) == 0: + response = 1 + else: + response = int(text_response) + except: + print("Error: Value must be a number between 1 and 6, leave blank for default\n") + return styles[response] + + def _input(self, prompt_text): + """ + Prompt the user for input. + + The input command will change depending on the version of python + installed. To maintain support for 2 and earlier, we must use + raw_input in that case. Else use input. + """ + + # Try to get the python version. This command is only available in + # python 2 and later, so it's important that we catch the exception + # if the command isn't found. + try: + majorversion = sys.version_info[0] + except: + majorversion = 1 + + # Use the correct function to prompt the user for input depending on + # what python version the code is running in. + if majorversion >= 3: + return input(prompt_text) + else: + return raw_input(prompt_text) diff --git a/nbconvert2.py b/nbconvert2.py index 6bb0da5..3f4864b 100755 --- a/nbconvert2.py +++ b/nbconvert2.py @@ -29,6 +29,7 @@ from IPython.config.loader import ConfigFileNotFound from IPython.utils.traitlets import Unicode, Bool from converters.transformers import (ExtractFigureTransformer) +from converters.sphinx_transformer import (SphinxTransformer) from converters.config import GlobalConfigurable @@ -105,7 +106,13 @@ class NbconvertApp(Application): """Convert a notebook in one step""" ipynb_file = (self.extra_args or [None])[2] - C = ConverterTemplate(config=self.config) + # If you are writting a custom transformer, append it to the dictionary + # below. + userpreprocessors = {} + userpreprocessors["SphinxTransformer"] = SphinxTransformer(config=self.config) # Sphinx templates + + # Create the converter + C = ConverterTemplate(config=self.config, preprocessors=userpreprocessors) output, resources = C.from_filename(ipynb_file) if self.stdout : diff --git a/profile/latex_sphinx_base.nbcv b/profile/latex_sphinx_base.nbcv index 9fd9219..693a76c 100644 --- a/profile/latex_sphinx_base.nbcv +++ b/profile/latex_sphinx_base.nbcv @@ -1,8 +1,14 @@ c = get_config() -#Inherit +# Inherit load_subconfig('latex_base.nbcv') -#Overrides +# Overrides c.ConverterTemplate.template_file='latex_sphinx_base' c.NbconvertApp.write = True + +#TODO: assign from c.ConverterTemplate.pre_transformer_order +Transformers = ['haspyout_transformer'] +Transformers.append('SphinxTransformer') # Add Sphinx transformer +c.ConverterTemplate.pre_transformer_order = Transformers + diff --git a/templates/tex/latex_sphinx_base.tplx b/templates/tex/latex_sphinx_base.tplx index 26d120c..59fe839 100644 --- a/templates/tex/latex_sphinx_base.tplx +++ b/templates/tex/latex_sphinx_base.tplx @@ -11,13 +11,14 @@ ((*- extends 'latex_base.tplx' -*)) ((* block header *)) + % Header, overrides base - + % Make sure that the sphinx doc style knows who it inherits from. \def\sphinxdocclass{(((parentdocumentclass)))} - + % Declare the document class - \documentclass[letterpaper,10pt,english]{sphinx(((documentclass)))} + \documentclass[letterpaper,10pt,english]{((( resources.sphinx_texinputs )))/sphinx(((documentclass)))} % Imports \usepackage[utf8]{inputenc} @@ -26,18 +27,18 @@ \usepackage{babel} \usepackage{times} \usepackage{import} - \usepackage[Bjarne]{fncychap} + \usepackage[((( resources.sphinx_chapterstyle )))]{((( resources.sphinx_texinputs )))/fncychap} \usepackage{longtable} - \usepackage{sphinx} + \usepackage{((( resources.sphinx_texinputs )))/sphinx} \usepackage{multirow} % Document level variables \title{((( nb.metadata.name )))} - \date{\today} - \release{} - \author{Unknown Author} + \date{((( nb.metadata.date )))} + \release{((( nb.metadata.version )))} + \author{((( nb.metadata.author )))} \newcommand{\sphinxlogo}{} - \renewcommand{\releasename}{Release} + \renewcommand{\releasename}{((( nb.metadata.release )))} \makeindex