From 48a4698155a69ba0fadeb93d105a01cbbed468e4 Mon Sep 17 00:00:00 2001 From: Tyler Makaro Date: Sun, 28 Jul 2019 10:48:21 -0700 Subject: [PATCH] make a default global location for custom user templates (#1028) Make a default global locations for custom user templates --- docs/source/customizing.ipynb | 44 +++++++++++++++++++++++-- nbconvert/exporters/html.py | 5 +++ nbconvert/exporters/latex.py | 5 +++ nbconvert/exporters/templateexporter.py | 15 +++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/docs/source/customizing.ipynb b/docs/source/customizing.ipynb index 4da09ebd1..ec780c74a 100644 --- a/docs/source/customizing.ipynb +++ b/docs/source/customizing.ipynb @@ -206,6 +206,40 @@ "!jupyter nbconvert --to python 'example.ipynb' --stdout --template=simplepython.tpl" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Saving Custom Templates\n", + "\n", + "By default, nbconvert finds templates from a few locations.\n", + "\n", + "The recommended place to save custom templates, so that they are globally accessible to nbconvert, is your jupyter data directories:\n", + "\n", + "- share/jupyter\n", + " - nbconvert\n", + " - templates\n", + " - html\n", + " - latex\n", + "\n", + "The HTML and LaTeX/PDF exporters will search the html and latex subdirectories for templates, respectively.\n", + "\n", + "To find your jupyter configuration directory you can use:\n", + "\n", + "```python\n", + "from jupyter_core.paths import jupyter_path\n", + "print(jupyter_path('nbconvert','templates'))\n", + "```\n", + "\n", + "Additionally,\n", + "\n", + "```python\n", + "TemplateExporter.template_path=['.']\n", + "```\n", + "\n", + "defines an additional list of paths that nbconvert can look for user defined templates. It defaults to searching for custom templates in the current working directory and can be changed through configuration options." + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -376,7 +410,13 @@ "source": [ "### A few gotchas\n", "\n", - "Jinja blocks use `{% %}` by default which does not play nicely with LaTeX, so those are replaced by `((* *))` in LaTeX templates." + "Jinja uses `%`, `{`, and `}` for syntax by default which does not play nicely with LaTeX. In LaTeX, we have the following replacements:\n", + "\n", + "| Syntax | Default | LaTeX |\n", + "|----------|---------|---------|\n", + "| block | {% %} | ((* *)) |\n", + "| variable | {{ }} | ((( ))) |\n", + "| comment | {# #} | ((= =)) |" ] }, { @@ -24921,7 +24961,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.1" + "version": "3.7.3" } }, "nbformat": 4, diff --git a/nbconvert/exporters/html.py b/nbconvert/exporters/html.py index cf6d0871b..bf2b3c005 100644 --- a/nbconvert/exporters/html.py +++ b/nbconvert/exporters/html.py @@ -8,6 +8,7 @@ from traitlets import default, Unicode from traitlets.config import Config +from jupyter_core.paths import jupyter_path from jinja2 import contextfilter from nbconvert.filters.highlight import Highlight2HTML @@ -36,6 +37,10 @@ def _file_extension_default(self): def _default_template_path_default(self): return os.path.join("..", "templates", "html") + @default('template_data_paths') + def _template_data_paths_default(self): + return jupyter_path("nbconvert", "templates", "html") + @default('template_file') def _template_file_default(self): return 'full.tpl' diff --git a/nbconvert/exporters/latex.py b/nbconvert/exporters/latex.py index eae351308..b9f82eb4e 100644 --- a/nbconvert/exporters/latex.py +++ b/nbconvert/exporters/latex.py @@ -7,6 +7,7 @@ from traitlets import Unicode, default from traitlets.config import Config +from jupyter_core.paths import jupyter_path from nbconvert.filters.highlight import Highlight2Latex from nbconvert.filters.filter_links import resolve_references @@ -38,6 +39,10 @@ def _default_template_path_default(self): @default('template_skeleton_path') def _template_skeleton_path_default(self): return os.path.join("..", "templates", "latex", "skeleton") + + @default('template_data_paths') + def _template_data_paths_default(self): + return jupyter_path("nbconvert", "templates", "latex") #Extension that the template files use. template_extension = Unicode(".tplx").tag(config=True) diff --git a/nbconvert/exporters/templateexporter.py b/nbconvert/exporters/templateexporter.py index 77059428c..4a3fff78b 100644 --- a/nbconvert/exporters/templateexporter.py +++ b/nbconvert/exporters/templateexporter.py @@ -15,6 +15,8 @@ from traitlets.config import Config from traitlets.utils.importstring import import_item from ipython_genutils import py3compat +from jupyter_core.paths import jupyter_path +from jupyter_core.utils import ensure_dir_exists from jinja2 import ( TemplateNotFound, Environment, ChoiceLoader, FileSystemLoader, BaseLoader, DictLoader @@ -184,6 +186,11 @@ def _raw_template_changed(self, change): help="Path where the template skeleton files are located.", ).tag(affects_environment=True) + template_data_paths = List( + jupyter_path('nbconvert','templates'), + help="Path where templates can be installed too." + ).tag(affects_environment=True) + #Extension that the template files use. template_extension = Unicode(".tpl").tag(config=True, affects_environment=True) @@ -391,7 +398,15 @@ def _create_environment(self): """ here = os.path.dirname(os.path.realpath(__file__)) + additional_paths = self.template_data_paths + for path in additional_paths: + try: + ensure_dir_exists(path, mode=0o700) + except OSError: + pass + paths = self.template_path + \ + additional_paths + \ [os.path.join(here, self.default_template_path), os.path.join(here, self.template_skeleton_path)]