Can jupyter notebook web UI be used with custom templates? - python

I have seen many posts on how to use a custom template when rendering LaTeX from a jupyter notebook (eg hide code in jupyter notebook) and have successfully implemented the answer described here (custom template location) eg:
~/dev/notebooks$ jupyter nbconvert --to=latex filename.ipynb --Application.log_level='DEBUG'
works fine (and applies the custom template specified in my ~/.jupyter/jupyter_nbconvert_config.py).
But how can I set the jupyter web UI to function the same way using:
File->Download as->LaTeX (.tex)
Thanks in advance.

I found the solution jupyter_notebook_config.py. Basically, the jupyter application determines the applied template, which is why it was working fine with:
jupyter nbconvert ...
but was not working with:
File->Download as->LaTeX (.tex)
So, by using this ~/.jupyter/jupyter_notebook_config.py:
import os
c = get_config()
c.TemplateExporter.template_path = [os.path.expanduser('~/.jupyter/templates'), \
'/usr/local/bin/miniconda3/envs/MyEnv/lib/python3.6/site-\
packages/jupyter_contrib_nbextensions/templates', '.']
c.LatexExporter.template_file = 'custom_latex.tplx'
and placing a 'custom_latex.tplx' in the base template directory. I can set a default template (that does nothing) and then each user can override that default template as they choose (this is for a jupyter hub installation). If you don't need this generic behavior (ie you aren't on a jupyter hub), you can ignore the default template portion entirely.
For completeness...
default template:
((= Nbconvert custom style for LaTeX export =))
((*- extends 'article.tplx' -*))
%==============================================================================\
=
% Custom definitions
%==============================================================================\
=
((* block definitions *))
((( super() )))
% Pygments definitions
((( resources.latex.pygments_definitions )))
% Exact colors from NB
\definecolor{incolor}{rgb}{0.0, 0.0, 0.5}
\definecolor{outcolor}{rgb}{0.545, 0.0, 0.0}
% Don't number sections
\renewcommand{\thesection}{\hspace*{-0.5em}}
\renewcommand{\thesubsection}{\hspace*{-0.5em}}
((* endblock definitions *))
% No title
((* block maketitle *))((* endblock maketitle *))
%==============================================================================\
=
% Latex Article
%==============================================================================\
=
% You can customize your LaTeX document here, e.g. you can
% - use a different documentclass like
% \documentclass{report}
% - add/remove packages (like ngerman)
((* block docclass *))
% !TeX spellcheck = de_DE
% !TeX encoding = UTF-8
\documentclass{article}
((* endblock docclass *))
personal template:
((= Nbconvert custom style for LaTeX export =))
((*- extends 'nbextensions.tplx' -*))
%==============================================================================\
=
% Custom definitions
%==============================================================================\
=
((* block definitions *))
((( super() )))
% Pygments definitions
((( resources.latex.pygments_definitions )))
% Exact colors from NB
\definecolor{incolor}{rgb}{0.0, 0.0, 0.5}
\definecolor{outcolor}{rgb}{0.545, 0.0, 0.0}
% Don't number sections
\renewcommand{\thesection}{\hspace*{-0.5em}}
\renewcommand{\thesubsection}{\hspace*{-0.5em}}
((* endblock definitions *))
% No title
((* block maketitle *))((* endblock maketitle *))
%==============================================================================\
=
% Latex Article
%==============================================================================\
=
% You can customize your LaTeX document here, e.g. you can
% - use a different documentclass like
% \documentclass{report}
% - add/remove packages (like ngerman)
((* block docclass *))
% !TeX spellcheck = de_DE
% !TeX encoding = UTF-8
\documentclass{article}
% this is all unnecessary when extending nbextensions.tplx + hide_input_all
\usepackage{verbatim} %for {comment}
\usepackage{fancyvrb}
\renewenvironment{Verbatim}{\comment}{\endcomment}
((* endblock docclass *))
Hope this helps someone else - I don't think the documentation is clear on this point at all.

Related

How do I export images of graphs to a pdf in Jupyter?

I do not wish to export the entire notebook as a pdf - I've searched and found solutions for that problem. I want to only export the plots in my notebook to a pdf. Is there a Python library does allows for this?
The Jupyter nbconvert command allows specifying a custom template.
Michael Goerz has written a full custom template for LaTeX/PDFs here:
https://gist.github.com/goerz/d5019bedacf5956bcf03ca8683dc5217
To only print the graphs, you could modify it to blank out any sections other than the output cells, like so:
% Tell the templating engine what output template we want to use.
((* extends 'article.tplx' *))
% Template will setup imports, etc. as normal unless we override these sections.
% Leave title blank
((* block title -*))
((*- endblock title *))
% Leave author blank
((* block author -*))
((* endblock author *))
% Etc.
((* block maketitle *))
((* endblock maketitle *))
% Don't show "input" prompt
((*- block in_prompt -*))
((*- endblock in_prompt -*))
% Hide input cells
((*- block input -*))
((*- endblock input -*))
% Don't show "output" prompt
((*- block output_prompt -*))
((*- endblock output_prompt -*))
% Let template render output cells as usual
To generate a LaTeX file, save the above as custom_article.tplx and run:
jupyter nbconvert --to=latex --template=custom_article.tplx file.ipynb
To generate the LaTeX file and PDF in a single command:
jupyter nbconvert --to=pdf --template=custom_article.tplx file.ipynb
This is probably not the most elegant answer, but it's also extremely flexible in case you want to do more than just put each plot on a page. You can use LaTeX to collect all graphs in a single pdf after exporting them as images. Here's an example where we save the graphs as report/imgs/*.png, then write a report/report.tex file and compile it with pdflatex into a final report/report.pdf.
import numpy as np
import matplotlib.pyplot as plt
Create and save two images:
plt.bar(np.arange(5), np.arange(5)*2)
plt.savefig('report/imgs/fig1.png')
plt.bar(np.arange(6), np.arange(6)**2 - 1, color = 'g')
plt.savefig('report/imgs/fig2.png')
Write a .tex file to display both images:
img_data = ['fig1', 'fig2']
latex_src = '\\documentclass{article}\n'
latex_src += '\\usepackage{graphicx}\n'
latex_src += '\\graphicspath{{./imgs/}}\n'
latex_src += '\\begin{document}\n'
for image in img_data:
latex_src += '\t\\begin{figure}[h]\n'
latex_src += f'\t\t\\includegraphics{{{image}}}\n'
latex_src += '\t\\end{figure}\n'
latex_src += '\\end{document}'
with open('report/report.tex', 'w', encoding = 'utf-8') as handle:
handle.write(latex_src)
print(latex_src)
\documentclass{article}
\usepackage{graphicx}
\graphicspath{{./imgs/}}
\begin{document}
\begin{figure}[h]
\includegraphics{fig1}
\end{figure}
\begin{figure}[h]
\includegraphics{fig2}
\end{figure}
\end{document}
And finally compile:
!cd report && pdflatex report.tex

Extending Jinja's {% trans %} to use JavaScript variables

I'd like to extend the behaviour of trans by rendering variables not as as values from the context, but instead as html (without using the context). My aim is to be able to populate those variables on the client through JavaScript.
Jinja as it seems doesn't allow for a great deal of customisation of this kind or I'm just unable to find the right hooks.
Here's what I'd like to achieve:
{% etrans name=username %}
My name is {{ name }}
{% endetrans %}
This should render to:
My name is <span id='#username'></span>
Of course, I could just use the normal {% trans %} directive and pass my html code to template.render(html_code_params), but that would require to have them defined in the template and the rendering code which I'd like to avoid.
Here's what I got so far (not much) which allows for a new etrans tag and the ability to use whatever goodies InternationalizationExtension has to offer.
from jinja2.ext import InternationalizationExtension
from jinja2.runtime import concat
class JavaScriptVariableExtension(InternationalizationExtension):
tagname = 'etrans'
tags = set([tagname])
def _parse_block(self, parser, allow_pluralize):
"""Parse until the next block tag with a given name.
Copy from InternationalizationExtension, as this uses hardcoded
`name:endtrans` instead of relying on tag name
"""
referenced = []
buf = []
while 1:
if parser.stream.current.type == 'data':
buf.append(parser.stream.current.value.replace('%', '%%'))
next(parser.stream)
elif parser.stream.current.type == 'variable_begin':
next(parser.stream)
name = parser.stream.expect('name').value
referenced.append(name)
buf.append('%%(%s)s' % name)
parser.stream.expect('variable_end')
elif parser.stream.current.type == 'block_begin':
next(parser.stream)
# can't use hardcoded "endtrans"
# if parser.stream.current.test('name:endtrans'):
if parser.stream.current.test('name:end%s' % self.tagname):
break
elif parser.stream.current.test('name:pluralize'):
if allow_pluralize:
break
parser.fail('a translatable section can have only one '
'pluralize section')
parser.fail('control structures in translatable sections are '
'not allowed')
elif parser.stream.eos:
parser.fail('unclosed translation block')
else:
assert False, 'internal parser error'
return referenced, concat(buf)
i18n_extended = JavaScriptVariableExtension
I don't mind overloading more methods (although the reason for above one should perhaps fixed upstream).
Stepping through the code is quite an interesting adventure. However, I hit a snag and am interested if anyone can give some advice.
The problem I see is that during the compilation, the function context.resolve() gets baked into the compiled code. jinja2.jinja2.compiler.CodeGenerator doesn't really allow any different handling here (correct me if I'm wrong). Ideally, I would define another node (for the variable) and this node would handle the way it's dealt with during compilation, but I don't see how this is possible. I might be too focussed on this as a solution, so perhaps someone can provide alternatives.
As suggested by #Garrett's comment, a much easier solution is to pass in a function to the template renderer that interpolates the variables. In my case, my target client-side framework is Angular, but this also works for any JS variables that you want to use within a {% trans %} environment. Here are the building blocks:
def text_to_javascript(string):
# modify as needed...
return "<span>{{ %s }}</span>" % string
def render():
tmpl = jinja_env.get_template(template_filename)
return tmpl.render({'js': text_to_javascript})
And this how I make use of it in the template file:
{% trans username=js('user.name') %}
My name is {{ username }}
{% endtrans %}
In the Angular controller, the variable user is bound to the $scope like so:
$scope.user = {'name': 'Bugs Bunny'}

export notebook to pdf without code [duplicate]

This question already has answers here:
How to hide code from cells in ipython notebook visualized with nbviewer?
(23 answers)
Closed 4 years ago.
I have a large notebook with a lot of figures and text. I want to convert it to a html file. However, I don't want to export the code. I am using the following command
ipython nbconvert --to html notebook.ipynb
But this option also exports the code. Is there a way to convert the notebook to html without the code?
I found this article interesting it explains how to remove the input columns :
you have to create a template file named "hidecode.tplx" in same directory as the notebook you want to convert and add those line in it :
((*- extends 'article.tplx' -*))
((* block input_group *))
((*- if cell.metadata.get('nbconvert', {}).get('show_code', False) -*))
((( super() )))
((*- endif -*))
((* endblock input_group *))
And after run this command it will use pdfLatex to convert the notebook in pdf via latex:
jupyter nbconvert --to pdf --template hidecode Example.ipynb
or if you want to edit you can convert it to a .tex document and use pdfLatex to put it in pdf :
jupyter nbconvert --to latex --template hidecode Example.ipynb
EDIT Sept 2018:
ipython nbconvert is deprecated. It will be replaced by jupyter nbconvert: So we replace the command ipython with jupyter
EDIT Feb 2021: (This is my best answer here, so let me take care of it)
Following #Mrule comment adding --no-input flag will make it work without the template...
jupyter nbconvert --to latex --no-input Example.ipynb
PS: If you are getting issue saying :
LaTeX error related to tcolorbox.sty not found
Please refer to this guide to update your tex installation and this question
I was seeking the same question in SO and finally turned out to a very straightforward way:
Assuming using Firefox(57) + Win7
Run Jupyter notebook and download the notebook in the browser: File->Download as->HTML and you will get a html page with code and output.
Open the exported HTML with browser and activate the browser console with key F12
Run following command in the console:
document.querySelectorAll("div.input").forEach(function(a){a.remove()})
The code removes all input div DOM. Then right mouse button and chose "Save Page As" and Save the "Complete page" (not single page).
You will get a page with an associated folder in windows. Use a trick by zip the html page and then extract to unbind the associated. The folder is useless.
Now it is a single html page without code. You can re-distribute it or print it as PDF.
If you are not using Firefox or Windows, please adjust the above 3-6 steps.
Here is how I do it:
I simply download my notebook as html.
Then run this python script to convert that html file so that prompts and code cells are gone:
FILE = "/somewhere/myHTMLFile.html"
with open(FILE, 'r') as html_file:
content = html_file.read()
# Get rid off prompts and source code
content = content.replace("div.input_area {","div.input_area {\n\tdisplay: none;")
content = content.replace(".prompt {",".prompt {\n\tdisplay: none;")
f = open(FILE, 'w')
f.write(content)
f.close()
That script bascially adds the CSS 'display: none' attribute for all divs of class 'prompt' or 'input_area'.
As a generalization of this answer, so that hidecode template could be accessible from multiple locations:
Go into your home directory:
cd ~/.jupyter
Create jupyter_nbconvert_config.py under this directory.
Write the following into the .py file (Change user_name to your user name):
c = get_config()
c.TemplateExporter.template_path = ['.', "~/.jupyter" ]
c.LatexExporter.template_path = ['.', "~/.jupyter"]
Create a template file under this directory, named hidecode.tplx or hidecode.tpl:
((*- extends 'article.tplx' -*))
((* block input_group *))
((*- if cell.metadata.get('nbconvert', {}).get('show_code', False) -*))
((( super() )))
((*- endif -*))
((* endblock input_group *))
Then, the following should generate a PDF without .ipynb files' codes (Change file_name to your file name):
jupyter nbconvert --to pdf '<file_name>.ipynb' --template=hidecode.tpl
You can add this css to your page and then print into PDF from the browser. Note that the code is only hidden, not removed.
div.output_prompt { visibility: hidden; }
*{ font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif !important }
.input,#header { display: none; }
To make sure you remove the code you should use something like
$(".input").remove()
As far as I know there is no way to generate via latex a PDF that does not include the code. It would be great to have a jupyter notebook extension that does it though...
nbconvert uses templates to convert the notebook's JSON into a document; for example, in the markdown template that comes with nbconvert, markdown.tpl:
{% block input %}
{% if nb.metadata.language_info %}{{ nb.metadata.language_info.name }}{% endif %}
{{ cell.source}}
{% endblock input %}
which prints each cell's source in the output. If you delete {{ cell.source}} then the cell source will not print out. There are corresponding blocks in the HTML and Latex templates as well.
Better yet, make your own template that does exactly what you want :)

SaltStack: Use regexps in pillar file

I would like to do some basic pillar value settings for all boxes so that I can use them later in a unified way. Our minions are usually named in this format:
<project>-<env>.<role>-<sequence>.<domain>
Example pillar/base/top.sls:
base:
'*':
- basics
'I#project:mycoolproject and I#role:nginx':
- etc.
Example pillar/base/basics/init.sls:
{% if '-live.' in grains['id'] %}
env: production
{% elif '-qa.' in grains['id'] %}
env: qa
{% elif '-staging.' in grains['id'] %}
env: staging
{% else %}
env:
{% endif %}
{% set role = re.match("(?:live|qa|staging)\.([a-z_\-]+)\-', grains['id']).group(1) -%}
role: {{ role }}
The env part obviously works but I can't get the regex working. As far as I understood there is no way to import python module (i.e. import re) in jinja template. Any suggestions how to get regex functionality available in the pillar file if possible at all?
The simple answer is, "no". There is not a way to inject regex functionality directly into the jinja environment (I'm sure there's a way to extend jinja, but anyway..)
The way I addressed this was with an external module function, id_info.explode() and an external pillar.
Enable external modules on the master:
external_modules: /srv/extmod
External modules do not require any sort of special infrastructure--they are just regular python modules (not packages, mind you--the loader doesn't currently know how to properly side-load a package yet)
Put your python+regex logic there. Return a dictionary, assembled to your your liking.
Your external module would go in /srv/extmod/modules. You can call call this function from your pillar.sls
{% id_info = __salt__[id_info.explode()] -%}
{% subcomponent = id_info['subcomponent'] -%}
{% project = id_info['project'] -%}
etc...
A couple things to know:
The salt-master has to be restarted when an external module is added or modified. There isn't a way that I know of to incite the equivalent of a saltutil.refresh_modules() call on the salt-master, so there ya go.
The external_modules directive is not just for execution modules. In this scenario, you would also create /srv/extmod/{pillar,runners,outputers,etc}.
These modules are only available on the master

Changing style of PDF-Latex output through IPython Notebook conversion

Currently with the following command of my .ipynb file:
$ ipython nbconvert --to latex --post PDF Untitled1.ipynb --SphinxTransformer.author="John Doe"
[NbConvertApp] Using existing profile dir: u'/Users/me-macmini/.ipython/profile_default'
[NbConvertApp] Converting notebook Untitled1.ipynb to latex
[NbConvertApp] Support files will be in Untitled1_files/
[NbConvertApp] Loaded template article.tplx
[NbConvertApp] Writing 12876 bytes to Untitled1.tex
[NbConvertApp] Building PDF
[NbConvertApp] Running pdflatex 3 times: [u'pdflatex', u'Untitled1.tex']
[NbConvertApp] Running bibtex 1 time: [u'bibtex', u'Untitled1']
[NbConvertApp] WARNING | bibtex had problems, most likely because there were no citations
[NbConvertApp] Removing temporary LaTeX files
[NbConvertApp] PDF successfully created
With IPython 2.1, I got the latex file that are formatted with the standard classical style:
My questions are:
What should I do so that I can get the following style, right from ipython command?
Why the above command doesn't enable the author to appear?
Like the OP, I'm not very happy with IPython 2 output from nbconvert. Since the converter no longer uses the Sphinx documentclass or the Sphinx preprocessing system, you can't use the SphinxTransformer calls on the nbconverter line.
The Rude-and-Crude Way
Drop --post PDF so nbconvert creates just the .tex file. Then, edit the .tex file to make it prettier. Then, run pdflatex on it a few times.
To make yourself the author, add a line like the following right after the \title line in the he .tex file:
\author{Never Saint}
You can find nice templates to help you make output look like what you want at latextemplates.com.
The Root-User's Way
Another approach is to roll a new template, starting with the ones in .../IPython/nbconvert/templates/latex. As the root user, add an article1.tplx file next to article.tplx and report.tplx. The following version creates a different output style that I personally find useful. The "margins" block produces front matter for LaTex, and the "predoc" block produces commands and text that are inserted at the start of the document. I blank out the "maketitle" block so there's no title page. Delete my empty "maketitle" block if you want to have a title page with an author and a date.
Usage: nbconvert --to latex yourNotebook.ipynb --template article1 --to PDF
% Default to the notebook output style
((* if not cell_style is defined *))
((* set cell_style = 'style_ipython.tplx' *))
((* endif *))
% Inherit from the specified cell style.
((* extends cell_style *))
%===============================================================================
% Latex article1, based on Article
%===============================================================================
((* block docclass *))
\documentclass{article}
((* endblock docclass *))
((* block margins *))
\usepackage{blindtext}
\usepackage{mathptmx}% Times Roman font
\usepackage[scaled=.90]{helvet}
\usepackage{xcolor}
\usepackage{titlesec}
\titleformat{\title}[display]
{\normalfont\sffamily\huge\bfseries\color{blue}}
{\titlename}{20pt}{\Huge}
\titleformat{\section}
{\normalfont\sffamily\Large\bfseries\color{darkgray}}
{\subsection}{1em}{}
\titleformat{\subsection}
{\normalfont\sffamily\Large\bfseries\color{darkgray}}
{\thesubsection}{1em}{}
\parindent=0pt
\parskip=6pt
((* endblock margins *))
((* block predoc *))
\begin{document}
\pagestyle{plain}
\thispagestyle{plain}
\pagenumbering{arabic}
\setcounter{page}{5}
\lfoot{\copyright 2014}
This document is composed as an
\href{http://ipython.org/notebook.html}{IPython} notebook. The printed
version of this document was generated from the \texttt{IPython}
notebook, using the \texttt{ipython nbconvert} utility to generate a
\texttt{Latex} document.
((* block maketitle *))((* endblock maketitle *))
((* block author *))\author{Put Your Name Here}((* endblock author *))
((* endblock predoc *))
Solving this problem is a real pain-in-the-butt. I also liked the iPython 0.x and 1.x styling. If you must have it, here's how you can do it.
Folks mentioned that you can create your own template. Well, iPython 1.x had perfectly good templates, so let's use them. I'm going to assume you have root on your machine, because we're going to hack our iPython's templates/latex directory.
# set for your python/ipython install
PYTHONLIB=/usr/lib64/python2.7/site-packages/
cd ${PYTHONLIB}/IPython/nbconvert/templates/latex
# download the files
for tplx in sphinx.tplx latex_article.tplx latex_book.tplx latex_basic.tplx; do
wget https://raw.githubusercontent.com/ipython/ipython/1.x/IPython/nbconvert/templates/latex/${tplx} -O old_${tplx}
done
# update for some renaming that we just did
for tplx in old_latex_*.tplx; do
sed -i 's|sphinx.tplx|old_sphinx.tplx|' ${tplx}
done
Now, the next step is to apply a patch to sphinx.tplx.
% cat sphinx_patch.patch
--- old_sphinx.tplx 2015-02-13 14:52:14.000000000 -0500
+++ mod_old_sphinx.tplx 2015-02-13 14:53:00.000000000 -0500
## -71,6 +71,7 ##
% Pygments requirements
\usepackage{fancyvrb}
\usepackage{color}
+
% ansi colors additions
\definecolor{darkgreen}{rgb}{.12,.54,.11}
\definecolor{lightgray}{gray}{.95}
## -83,6 +84,29 ##
\definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
\definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
+ %
+ % MEF NEW NEW MEF
+ %
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
+ \newenvironment{Shaded}{}{}
+ \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}}
+ \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}}
+ \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
+ \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
+ \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
+ \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
+ \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
+ \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}}
+ \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}}
+ \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
+ \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}}
+ \newcommand{\RegionMarkerTok}[1]{{#1}}
+ \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
+ \newcommand{\NormalTok}[1]{{#1}}
+ %
+ % MEF NEW NEW MEF
+ %
+
% Needed to box output/input
\usepackage{tikz}
\usetikzlibrary{calc,arrows,shadows}
## -374,7 +398,6 ##
((* if resources.sphinx.centeroutput *))
\begin{center}
((* endif -*))
-((( output.latex | strip_math_space )))
((*- if resources.sphinx.centeroutput *))
\end{center}
((* endif -*))
Cut and paste the above code to create the patch file. Then you can apply it with:
patch -p0 < sphinx_patch.patch
We're not done yet. Those templates need some support.
We'll do this back in the directory where the notebook you want to convert lives. We're going to create two python files. The first (I called it oldschool.py) does the preprocessing necessary to use the older templates. It is mostly scraped out of version 1.x iPython's nbconvert/transformers/sphinx.py and hacked to be a modern Preprocessor:
from __future__ import print_function, absolute_import
from IPython.nbconvert.preprocessors.base import Preprocessor
from IPython.utils.traitlets import Bool, Unicode
import os
class MySphinxyLatexPreprocessor(Preprocessor):
interactive = Bool(False, 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 chapter_style 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"
""")
publish_date = 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"
""")
chapter_style = 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)
""")
output_style = Unicode("notebook", config=True, help="""
Nbconvert Ipython
notebook input/output formatting style.
You may choose one of the following:
"simple (recommended for long code segments)"
"notebook" (default)
""")
center_output = Bool(False, config=True, help="""
Optional attempt to center all output. If this is false, no additional
formatting is applied.
""")
use_headers = Bool(True, config=True, help="""
Whether not a header should be added to the document.
""")
#Allow the user to override the title of the notebook (useful for
#fancy document titles that the file system doesn't support.)
overridetitle = Unicode("", config=True, help="")
def preprocess(self, nb, resources):
"""
Sphinx and LaTeX transformation to apply on each notebook.
Parameters
----------
nb : NotebookNode
Notebook being converted
resources : dictionary
Additional resources used in the conversion process. Allows
transformers to pass variables into the Jinja engine.
"""
# Generate Pygments definitions for Latex
from pygments.formatters import LatexFormatter
import sphinx
sphinxPath = os.path.realpath(os.path.join(sphinx.package_dir,
"texinputs"))
#
# MEF: set a latex resource
# old from latex preprocessor
# resources["latex"]["pygments_definitions"] = LatexFormatter(style='emacs').get_style_defs()
# Generate Pygments definitions for Latex
# old from sphinx transformer
# resources["sphinx"]["pygment_definitions"] = self._generate_pygments_latex_def()
# the mashup:
#resources["sphinx"]["pygment_definitions"] = \
# LatexFormatter(style='emacs').get_style_defs()
# used below
# MEF edit
resources.setdefault("sphinx", {})
#if not "sphinx" in resources:
# resources["sphinx"] = {}
#
# set sphinx resources
#
resources["sphinx"]["pygment_definitions"] = LatexFormatter().get_style_defs()
# LatexFormatter(style='emacs').get_style_defs()
# Try to use the traitlets.
resources["sphinx"]["author"] = self.author
resources["sphinx"]["version"] = self.version
resources["sphinx"]["release"] = self.release
# Use todays date if none is provided.
if self.publish_date:
resources["sphinx"]["date"] = self.publish_date
elif len(resources['metadata']['modified_date'].strip()) == 0:
resources["sphinx"]["date"] = date.today().strftime(text.date_format)
else:
resources["sphinx"]["date"] = resources['metadata']['modified_date']
# Sphinx traitlets.
resources["sphinx"]["chapterstyle"] = self.chapter_style
resources["sphinx"]["outputstyle"] = self.output_style
resources["sphinx"]["centeroutput"] = self.center_output
resources["sphinx"]["header"] = self.use_headers
# Find and pass in the path to the Sphinx dependencies.
resources["sphinx"]["texinputs"] = sphinxPath
#
# MEF edit
#
if self.overridetitle and len(self.overridetitle.strip()):
resources['metadata']['name'] = self.overridetitle.strip()
return nb, resources
The last file is easy ({config.py}).
c = get_config()
c.Exporter.preprocessors = ['oldschool.MySphinxyLatexPreprocessor']
Now, at the command line, you can do:
ipython nbconvert example.ipynb --to latex --config config.py --template old_latex_article.tplx --post PDF
ipython nbconvert example.ipynb --to latex --config config.py --template old_latex_book.tplx --post PDF
If you want to use basic (aka, {the old_latex_basic.tplx} file), you'll have to hack in the the main block of code we added to sphinx.tplx (the portion between the % MEF NEW NEW MEF comments).
You probably have to either select a different template, or build your own. Try e.g. adding the --template book argument to your nbconvert command.
Since IPython 2 doesn't have the book template anymore, you'll probably need to roll your own.

Categories