nbconvert 6: How to customize Latex template - python

I'm trying to create a nbconvert (6.x) template that slightly modifies the default latex template.
I created a "no_header" template in <userprofile>\Miniconda3\share\jupyter\nbconvert\templates\no_header:
.
+-- no_header
| +-- conf.json
| +-- no_header.tex.j2
The conf.json contains:
{
"base_template": "latex",
"mimetypes": {
"text/latex": true,
"text/tex": true,
"application/pdf": true
}
}
The no_header.tex.j2 contains:
((*- extends 'latex' -*))
((*- block packages -*))
asdf
((* endblock packages *))
I took the block name packages from the style_jupyter.tex.j2. This section contains some usepackage commands.
I then created a simple notebook and tried using the template to convert it to tex via the command:
jupyter nbconvert --to=latex --template=no_header my_nb.ipynb
The command successfully creates the tex output - But it does not seem to use the template. The output is the exact same if I omit the template parameter to the cli call. Also, the string asdf is not present in the generated file, further indicating that the template was not activated.
When running the above command with --debug, the no_header template is listed under the 'template paths' listing. Also, when I misspelled the template name I got an error, so I think the call does find the template, but somehow does not use it.
What I tried so far:
All the tutorials online only describe the old template format (single files)
The documentation of nbconvert does not contain an mwe
For the approach described above, I followed this github issue.
Can anyone help me here?

The conf.json file is fine, but I think you need to call your entrypoint index.tex.j2. The name of the template is defined by the directory, not the .j2 file name.
Then in your no_header/index.tex.j2, you then specify which template you want to inherit from, e.g. borrowing from the standard latex article you start like this:
((=- Default to the notebook output style -=))
((*- if not cell_style is defined -*))
((* set cell_style = 'style_jupyter.tex.j2' *))
((*- endif -*))
((=- Inherit from the specified cell style. -=))
((* extends cell_style *))
((*- block docclass -*))
\documentclass[11pt]{article}
((*- endblock docclass -*))
and to customize the packages section, you then add as in the question:
((*- block packages -*))
asdf
((* endblock packages *))
Presumably you'll want to put a lot more in the "packages" block. If you want to add to certain blocks rather than override, include a super() call.
The default latex template directory has a number of files which add quite a lot of latex commands; you can track the inheritance chain (in the above example starting from style_jupyter.tex.j2) to see what all the different blocks are called so you can tweak them as needed (e.g. "margins").

Related

Issues rendering MathJax using Sphinx due to HTML-CSS renderer

I just upgraded to the following:
Sphinx==1.8.5
nbconvert==5.4.1
pandoc==1.0.2
I have always been able to render math in docs via a jupyter notebook using Sphinx (the way it is done for seaborn). However, after upgrading, the math no longer renders! If I right click where the equation should be, I can change the math renderer to either "svg" or "CommonHTML" and everything is fine - it just doesn't render with the default "HTML-CSS" math renderer for whatever reason. My question is: how can I change the default renderer in my config file?
What I tried:
conf.py
...
extensions = [
...
'sphinx.ext.mathjax'
...
]
...
mathjax_config = {
'jax': ['input/TeX', 'output/CommonHTML']
}
However, this didn't change the default renderer like I thought it should. Does anyone know how to change the default renderer for MathJax within Sphinx?
Here is a gif:
Also, it would appear that MathJax is being loaded from CDN with a preferred config:
I am not sure how MathJax worked for you before, but based on the Sphinx-documentation MathJax is not included in Sphinx by default. You have to specify the mathjax_path in your conf.py either using a local version or a server hosted one from cdnjs for example.
While I wasn't able to get the mathjax_config approach to work, I was able to set the mathjax_path to a specific output processor, still through the CDN, which worked using CommonHTML.
So, an answer that works is to edit the conf.py file to include a line with:
...
mathjax_path = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"
...

Making Sphinx detect changes to auxiliary configuration/template files

I'm using Sphinx (v1.4.9, with Python 3.5.1 on Windows 7, 64-bit) to write a document set with MathJax enabled. I wanted to define custom LaTeX commands to clean up my source, so I implemented this approach by adding _templates\layout.html:
{% extends "!layout.html" %}
{% set script_files = script_files + ["_static/mjconf.js"] %}
and defining my custom commands in _static\mjconf.js:
MathJax.Hub.Config({
TeX: {
Macros: {
dsetarr: ['{\\small \\textsf{#1 Array } \\mathsf{(#2)} }', 2],
dsettype: ['{\\small \\textsf{#1}}', 1],
mtt: ['{\\texttt{#1}}' ,1],
sgn: ['{\\mathrm{sgn}#1}', 1]
}
}
});
This is all working great.
However, whenever I edit mjconf.js to add a new command or revise an existing one, Sphinx doesn't recognize that the configuration has changed and so a simple make html doesn't rebuild the docs like it does after an edit to conf.py. I have to make clean before the make html in order to see the effects of the changes to these custom MathJax commands.
How can I configure Sphinx to react to an edited mjconf.js by rebuilding the entire documentation set, just like it does for an edited conf.py?
There's make html -a, but that will not reflect updates to cross-references in your documentation. This would be the fastest option, though, if you have no cross-reference updates.
There's also make html -E in case you have cross-references that must be updated, too.
Finally there is make clean html, which deletes (cleans) the build directory, if your makefile has it, then builds HTML again.
In order to enable invocations such as make html -E as recommended by Steve Piercy, I changed my make.bat from this:
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
to this:
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source %2
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
The only change was appending %2 to the line initializing %ALLSPHINXOPTS%.

Defining os_path in ansible jinja template

I need to include an if statement in my httpd.conf template based on whether a directory exists.
Here is what i have so far
{% if ansible_distribution_major_version > 7 and os.path.exists ("/opt/myapp/testapp") %}Include conf/vhost.conf{% endif %}
I get an os is undefined error when i run the task. Any idea what i am doing wrong?
You can't write arbitrary Python code inside Jinja2 expression.
Run Ansible stat module and register result before templating and use this result instead of os.path.exists.

Understanding "Too many ancestors" from pylint

example.py:
'''
demo too many ancestors
'''
from flask_security.forms import RegisterForm
from wtforms.fields import TextField
class ExtendedRegisterForm(RegisterForm):
'''An extended register form'''
name = TextField('Name', [])
When I run pylint:
$ pylint -r n example.py
************* Module example
R: 7, 0: Too many ancestors (10/7) (too-many-ancestors)
What does this mean and how can I fix it?
The problem is that you inherit from a class which has itself (too) many ancestors: RegisterForm. In your case, you can't do a lot about this, beside stopping using it which is probably not an option. So you may want to disable this message for this class, eg:
class ExtendedRegisterForm(RegisterForm): # pylint: disable=too-many-ancestors
In addition to the disabling directives in the source code, you can configure this through the --max-parents= commandline option. You can also specify this in the config file (.pylintrc):
[DESIGN]
max-parents=15
As you can see I set it to 15 as many classes in Django (my project), particularly its view classes, will have hierarchies that are deeper than the default 7.
From documentation here: https://pylint.readthedocs.io/en/stable/technical_reference/features.html
too-many-ancestors (R0901): Too many ancestors (%s/%s) Used when
class has too many parent classes, try to reduce this to get a simpler
(and so easier to use) class.
basically Add to json or .pylintrc --max-parents='yourrequirednumber'
Note: --max-parents=7 is default
If using Visual Studio Code (VSC) you can easily override default config with adding
below code to settings.json
Go to --> UserSettings ctrl+, (default shortcut) --> click ... (more actions) --> open settings.json --> Add to overwrite Default settings this code:
"python.linting.pydocstyleArgs": ["--max-parents=25"]
NOTE2:
if pylint_django is not installed:
$ pip install pylint-django

Python Cheetah - Specify name/value pairs for templating

I am trying to template-ize my Apache httpd configuration for deployment to different environments and I would like to use the Python language Cheetah application to do so. However, I am having difficulty with the command line cheetah program and I believe its a combination of my misunderstanding Cheetah along with a lack of documentation.
My goal is to have a single httpd.conf template file and substitute variables from an environment specific definition file.
httpd.tmpl:
Listen $HTTP_PORT
...
#if $ENABLE_HTTPS == true
<Virtual Host *:$HTTPS_PORT>
...
</VirtualHost>
#end if
production.env:
HTTP_PORT=34120
HTTPS_PORT=34121
ENABLE_HTTPS=true
What is the command line needed to fill this Cheetah template? I've used:
cheetah f --oext conf --debug httpd
But obviously prod.env is not read as an input file. Adding an #include to the top of my template file:
#include "prod.env"
And none of my names are found:
Cheetah.NameMapper.NotFound: cannot find 'APACHE_PORT'
This is not the ideal situation anyway, because I want the ability to specify the name/value mapping file on the command line for each invocation of cheetah.
Thanks!
EDIT: I am aware that I can write a python script to perform the file reading and then substitute using the Cheetah API. However, I'm looking for a way to use the command line to fill my template.
SOLVED
Thanks to the documentation link provided by #pyfunc I now understand how to accomplish this. The main issue is to supply --env on the cheetah command line which passes the current environment variables to cheetah. These environment variables must be exported first however.
Cheetah wraps each chunk of #include text inside a nested Template object.
Use
#include raw "prod.env"
also
#set global $HTTP_PORT="34120"
To include different env files, you will have too templatize that too.
Please look at the following for examples that should help you.
http://packages.python.org/Cheetah/dev_guide/output.html

Categories

Resources