""" 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 (ActivatableTransformer) class SphinxTransformer(ActivatableTransformer): """ 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): """ Entry Since we are not interested in any additional manipulation on a cell by cell basis, we do not call the base implementation. """ if self.enabled: return self.Transform(nb, other) def Transform(self, nb, other): """ Sphinx transformation to apply on each notebook. """ 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)