Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support and prefer .jinja to _t for static templates #11165

Merged
merged 40 commits into from Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3e735ee
Templating: use '.jinja2' suffix on Jinja2 template files instead of …
jayaddison Jan 31, 2023
5ce9483
ruff suggestion: adopt union typing syntax (with support provided by …
jayaddison Feb 3, 2023
168cb23
Merge branch 'master' into templating/jinja2-suffix
jayaddison Feb 13, 2023
4a8a339
Update file extension: the 'jinja2' project has been renamed to 'jinj…
jayaddison Feb 19, 2023
eb9938a
Merge branch 'master' into templating/jinja2-suffix
jayaddison Feb 19, 2023
43f8b2b
Fixup: ruff lint error (missing trailing comma after multi-line multi…
jayaddison Feb 19, 2023
b2889de
Fixup: adjust trim-length for template suffix (was: seven characters …
jayaddison Feb 19, 2023
a720933
Localization: undo changes to resource files
jayaddison Mar 21, 2023
6f99cef
Merge branch 'master' into templating/jinja2-suffix
jayaddison Mar 21, 2023
d2af9b5
Logic adjustment and refactor: rename '_template_basename' utility me…
jayaddison Apr 6, 2023
526fdc7
Emit a more-generic PendingDeprecationWarning instead of RemovedInSph…
jayaddison Apr 6, 2023
cd0d61f
CHANGES: document the deprecation of the '_t' file-copy template suffix
jayaddison Apr 6, 2023
5ab2226
Code commentary / feature removal timeline: provide two years from to…
jayaddison Apr 6, 2023
b8570ab
Merge branch 'master' into templating/jinja2-suffix
jayaddison Apr 6, 2023
59534ea
CHANGES: Add issue thread number reference
jayaddison Apr 6, 2023
e38e78e
Cleanup: remove unused import
jayaddison Apr 6, 2023
6305f96
Documentation: update hint related to LaTeX template filenames
jayaddison Apr 6, 2023
dc850b7
Babel resource extraction: update latex template method mappings to i…
jayaddison Apr 6, 2023
04aa946
Babel resource extraction: update javascript template method mapping …
jayaddison Apr 6, 2023
8572661
Babel resource extraction: update latex template options to include r…
jayaddison Apr 6, 2023
0eb993d
Revert changes to latex file rendering
jayaddison Apr 6, 2023
0444616
LaTeX templating: re-migrate to preferred '.tex.jinja' template suffi…
jayaddison Apr 6, 2023
29fb6f0
Fixup: migrate imgmath LaTeX template to use .jinja suffix
jayaddison Apr 6, 2023
1630cc8
Test coverage: ensure that we have test coverage for the legacy LaTeX…
jayaddison Apr 6, 2023
d85f016
Fixup: migrate built-in preview.tex LaTeX template
jayaddison Apr 6, 2023
8475023
Merge branch 'master' into templating/jinja2-suffix
AA-Turner Apr 6, 2023
bc43d2e
CHANGES: Update deprecation note to mention built-in templates
jayaddison Apr 6, 2023
06aa004
imgmath LaTeX templating: provide backwards-compatibility in the case…
jayaddison Apr 6, 2023
7b061cf
Safety in code path where a multi-item iterable is expected to be red…
jayaddison Apr 6, 2023
abd8af5
Fixup: add missing import
jayaddison Apr 6, 2023
d8e3fa7
Revert "Logic adjustment and refactor: rename '_template_basename' ut…
jayaddison Apr 6, 2023
30c7318
Fixup: imgmath: fallback to template filename with .jinja suffix
jayaddison Apr 6, 2023
d0aa68a
Template suffix iteration: use the 'tuple' datatype instead of 'list'…
jayaddison Apr 7, 2023
299dbed
Documentation: add explanatory docstring to utility '_template_basena…
jayaddison Apr 7, 2023
c3b5cb9
Adjust date, add helper function
AA-Turner Apr 7, 2023
6600615
Add tests
AA-Turner Apr 7, 2023
9327357
Update ``theming.rst``
AA-Turner Apr 7, 2023
cccdfaf
Update CHANGES
AA-Turner Apr 7, 2023
cb9ea44
left -> removed
AA-Turner Apr 7, 2023
9a4410a
credits
AA-Turner Apr 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGES
Expand Up @@ -23,6 +23,11 @@ Deprecated
----------

* #11247: Deprecate the legacy ``intersphinx_mapping`` format
* #11165: Warn when the ``_t`` suffix is used for template files. The formal
deprecation process will begin no earlier than 31 December 2024.
Templates should change to use the ``.jinja`` filename suffix instead.
For more information, see :ref:`theming-static-templates`.
Patch by James Addison and Adam Turner

Features added
--------------
Expand Down Expand Up @@ -60,6 +65,10 @@ Features added
``= 'xelatex'``. Patch by Dimitar Dimitrov
* #11109, #9643: Add :confval:`python_display_short_literal_types` option for
condensed rendering of ``Literal`` types.
* #11165: Support the `officially recommended`_ ``.jinja`` suffix for template
files. Patch by James Addison

.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension

Bugs fixed
----------
Expand Down
46 changes: 42 additions & 4 deletions doc/development/theming.rst
Expand Up @@ -156,13 +156,51 @@ template static files as well as HTML files. Therefore, Sphinx supports
so-called "static templates", like this:

If the name of a file in the ``static/`` directory of a theme (or in the user's
static path, for that matter) ends with ``_t``, it will be processed by the
template engine. The ``_t`` will be left from the final file name. For
example, the *classic* theme has a file ``static/classic.css_t`` which uses
templating to put the color options into the stylesheet. When a documentation
static path, for that matter) ends with ``.jinja``, it will be processed by the
template engine. The ``.jinja`` will be removed from the final file name. For
example, the *classic* theme has a file ``static/classic.css.jinja`` which uses
templating to put the colour options into the stylesheet. When a documentation
is built with the classic theme, the output directory will contain a
``_static/classic.css`` file where all template tags have been processed.

.. versionchanged:: 6.2

The preferred suffix for static templates is now ``.jinja``, in line with
the Jinja project's `recommended file extension`_.

The ``_t`` file suffix for static templates is now considered 'legacy', and
support will eventually be removed. The standard deprecation process will
begin no earlier than 31 December 2024, at which point using ``_t`` suffixes
will emit ``RemovedInSphinx__Warning`` warnings.

If a static template with a ``_t`` suffix is detected, it will be processed
by the template engine, with the ``_t`` suffix removed from the final file
name.

To silence the warning for ``_t`` suffixes, the new
``sphinx.deprecation.OldJinjaSuffixWarning`` class has been added for use
with Python's standard `warning control`_ mechanisms. This class will be
removed no earlier than 31 December 2024, so guard any imports with a
try/except block.
For example, in a ``setup()`` function:

.. code:: python

import warnings

def setup(app):
try:
from sphinx.deprecation import OldJinjaSuffixWarning
except ImportError:
pass # Only silence the warning if it exists!
else:
warnings.filterwarnings('ignore', category=OldJinjaSuffixWarning)

...

.. _recommended file extension: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
.. _warning control: https://docs.python.org/3/library/warnings.html#the-warnings-filter


Use custom page metadata in HTML templates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 4 additions & 4 deletions doc/latex.rst
Expand Up @@ -1811,12 +1811,12 @@ Miscellany
.. hint::

As an experimental feature, Sphinx can use user-defined template file for
LaTeX source if you have a file named ``_templates/latex.tex_t`` in your
LaTeX source if you have a file named ``_templates/latex.tex.jinja`` in your
project.

Additional files ``longtable.tex_t``, ``tabulary.tex_t`` and
``tabular.tex_t`` can be added to ``_templates/`` to configure some aspects
of table rendering (such as the caption position).
Additional files ``longtable.tex.jinja``, ``tabulary.tex.jinja`` and
``tabular.tex.jinja`` can be added to ``_templates/`` to configure some
aspects of table rendering (such as the caption position).
jayaddison marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: 1.6
currently all template variables are unstable and undocumented.
Expand Down
5 changes: 3 additions & 2 deletions sphinx/builders/_epub_base.py
Expand Up @@ -603,7 +603,8 @@ def build_content(self) -> None:
html.escape(self.refnodes[0]['refuri'])))

# write the project file
copy_asset_file(path.join(self.template_dir, 'content.opf_t'), self.outdir, metadata)
content_t = path.join(self.template_dir, 'content.opf.jinja')
copy_asset_file(content_t, self.outdir, metadata)

def new_navpoint(self, node: dict[str, Any], level: int, incr: bool = True) -> NavPoint:
"""Create a new entry in the toc from the node at given level."""
Expand Down Expand Up @@ -686,7 +687,7 @@ def build_toc(self) -> None:
navpoints = self.build_navpoints(refnodes)
level = max(item['level'] for item in self.refnodes)
level = min(level, self.config.epub_tocdepth)
copy_asset_file(path.join(self.template_dir, 'toc.ncx_t'), self.outdir,
copy_asset_file(path.join(self.template_dir, 'toc.ncx.jinja'), self.outdir,
self.toc_metadata(level, navpoints))

def build_epub(self) -> None:
Expand Down
8 changes: 4 additions & 4 deletions sphinx/builders/changes.py
Expand Up @@ -133,10 +133,10 @@ def hl(no: int, line: str) -> str:
f.write(self.templates.render('changes/rstsource.html', ctx))
themectx = {'theme_' + key: val for (key, val) in
self.theme.get_options({}).items()}
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
self.outdir, context=themectx, renderer=self.templates)
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
self.outdir)
default_t = path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja')
copy_asset_file(default_t, self.outdir, context=themectx, renderer=self.templates)
basic = path.join(package_dir, 'themes', 'basic', 'static', 'basic.css')
copy_asset_file(basic, self.outdir)

def hl(self, text: str, version: str) -> str:
text = html.escape(text)
Expand Down
2 changes: 1 addition & 1 deletion sphinx/builders/epub3.py
Expand Up @@ -184,7 +184,7 @@ def build_navigation_doc(self) -> None:
# 'includehidden'
refnodes = self.refnodes
navlist = self.build_navlist(refnodes)
copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'), self.outdir,
copy_asset_file(path.join(self.template_dir, 'nav.xhtml.jinja'), self.outdir,
self.navigation_doc_metadata(navlist))

# Add nav.xhtml to epub file
Expand Down
2 changes: 1 addition & 1 deletion sphinx/builders/gettext.py
Expand Up @@ -283,7 +283,7 @@ def finish(self) -> None:
ensuredir(path.join(self.outdir, path.dirname(textdomain)))

context['messages'] = list(catalog)
content = GettextRenderer(outdir=self.outdir).render('message.pot_t', context)
content = GettextRenderer(outdir=self.outdir).render('message.pot.jinja', context)

pofn = path.join(self.outdir, textdomain + '.pot')
if should_write(pofn, content):
Expand Down
4 changes: 2 additions & 2 deletions sphinx/builders/latex/__init__.py
Expand Up @@ -402,7 +402,7 @@ def copy_support_files(self) -> None:
# use pre-1.6.x Makefile for make latexpdf on Windows
if os.name == 'nt':
staticdirname = path.join(package_dir, 'texinputs_win')
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
copy_asset_file(path.join(staticdirname, 'Makefile.jinja'),
self.outdir, context=context)

@progress_message(__('copying additional files'))
Expand Down Expand Up @@ -441,7 +441,7 @@ def write_message_catalog(self) -> None:
if self.context['babel'] or self.context['polyglossia']:
context['addtocaptions'] = r'\addto\captions%s' % self.babel.get_language()

filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty.jinja')
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())


Expand Down
18 changes: 9 additions & 9 deletions sphinx/cmd/quickstart.py
Expand Up @@ -370,29 +370,29 @@ def write_file(fpath: str, content: str, newline: str | None = None) -> None:
if 'quiet' not in d:
print(__('File %s already exists, skipping.') % fpath)

conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None
conf_path = os.path.join(templatedir, 'conf.py.jinja') if templatedir else None
if not conf_path or not path.isfile(conf_path):
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py.jinja')
with open(conf_path, encoding="utf-8") as f:
conf_text = f.read()

write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d))

masterfile = path.join(srcdir, d['master'] + d['suffix'])
if template._has_custom_template('quickstart/master_doc.rst_t'):
if template._has_custom_template('quickstart/master_doc.rst.jinja'):
msg = ('A custom template `master_doc.rst_t` found. It has been renamed to '
'`root_doc.rst_t`. Please rename it on your project too.')
print(colorize('red', msg))
write_file(masterfile, template.render('quickstart/master_doc.rst_t', d))
write_file(masterfile, template.render('quickstart/master_doc.rst.jinja', d))
else:
write_file(masterfile, template.render('quickstart/root_doc.rst_t', d))
write_file(masterfile, template.render('quickstart/root_doc.rst.jinja', d))

if d.get('make_mode') is True:
makefile_template = 'quickstart/Makefile.new_t'
batchfile_template = 'quickstart/make.bat.new_t'
makefile_template = 'quickstart/Makefile.new.jinja'
batchfile_template = 'quickstart/make.bat.new.jinja'
else:
makefile_template = 'quickstart/Makefile_t'
batchfile_template = 'quickstart/make.bat_t'
makefile_template = 'quickstart/Makefile.jinja'
batchfile_template = 'quickstart/make.bat.jinja'

if d['makefile'] is True:
d['rsrcdir'] = 'source' if d['sep'] else '.'
Expand Down
28 changes: 28 additions & 0 deletions sphinx/deprecation.py
Expand Up @@ -62,3 +62,31 @@ def __getattr__(name):

warnings.warn(message + " Check CHANGES for Sphinx API modifications.",
warning_class, stacklevel=3)


class OldJinjaSuffixWarning(PendingDeprecationWarning):
"""Warning class for ``_old_jinja_template_suffix_warning``.

This class exists only so that extensions and themes can silence the legacy
filename warning via Python's `warning control`_ mechanisms. See
:ref:`theming-static-templates` for an example.

This warning class will be removed, and the warning class changed to the
appropriate RemovedInSphinx_0Warning no earlier than 31 December 2024, at
which point the standard deprecation process for ``_t`` template suffixes
will start.

.. _warning control: https://docs.python.org/3/library/warnings.html#the-warnings-filter
"""


def _old_jinja_template_suffix_warning(filename: str) -> None:
if filename.endswith('_t'):
warnings.warn(
f"{filename!r}: the '_t' suffix for Jinja templates is deprecated. "
"If the file is a template, use the suffix '.jinja' instead. "
'For more information, see '
'https://www.sphinx-doc.org/en/master/development/theming.html#static-templates',
OldJinjaSuffixWarning,
stacklevel=3,
)
7 changes: 4 additions & 3 deletions sphinx/ext/apidoc.py
Expand Up @@ -102,7 +102,7 @@ def create_module_file(package: str, basename: str, opts: Any,
'qualname': qualname,
'automodule_options': options,
}
text = ReSTRenderer([user_template_dir, template_dir]).render('module.rst_t', context)
text = ReSTRenderer([user_template_dir, template_dir]).render('module.rst.jinja', context)
write_file(qualname, text, opts)


Expand Down Expand Up @@ -138,7 +138,8 @@ def create_package_file(root: str, master_package: str, subroot: str, py_files:
'show_headings': not opts.noheadings,
'maxdepth': opts.maxdepth,
}
text = ReSTRenderer([user_template_dir, template_dir]).render('package.rst_t', context)
engine = ReSTRenderer([user_template_dir, template_dir])
text = engine.render('package.rst.jinja', context)
write_file(pkgname, text, opts)

if submodules and opts.separatemodules:
Expand All @@ -163,7 +164,7 @@ def create_modules_toc_file(modules: list[str], opts: Any, name: str = 'modules'
'maxdepth': opts.maxdepth,
'docnames': modules,
}
text = ReSTRenderer([user_template_dir, template_dir]).render('toc.rst_t', context)
text = ReSTRenderer([user_template_dir, template_dir]).render('toc.rst.jinja', context)
write_file(name, text, opts)


Expand Down
19 changes: 12 additions & 7 deletions sphinx/ext/imgmath.py
Expand Up @@ -19,6 +19,7 @@
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.deprecation import _old_jinja_template_suffix_warning
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging, sha1
Expand Down Expand Up @@ -95,16 +96,20 @@ def generate_latex_macro(image_format: str,
}

if config.imgmath_use_preview:
template_name = 'preview.tex_t'
template_name = 'preview.tex'
else:
template_name = 'template.tex_t'
template_name = 'template.tex'

for template_dir in config.templates_path:
template = path.join(confdir, template_dir, template_name)
if path.exists(template):
return LaTeXRenderer().render(template, variables)

return LaTeXRenderer(templates_path).render(template_name, variables)
# TODO: deprecate '_t' template suffix support after 2024-12-31
for template_suffix in ('_t', '.jinja'):
template = path.join(confdir, template_dir, template_name + template_suffix)
if path.exists(template):
_old_jinja_template_suffix_warning(template)
return LaTeXRenderer().render(template, variables)

# Default: fallback to a pathless in-library jinja template
return LaTeXRenderer(templates_path).render(f"{template_name}.jinja", variables)


def ensure_tempdir(builder: Builder) -> str:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 16 additions & 3 deletions sphinx/util/fileutil.py
Expand Up @@ -8,13 +8,27 @@

from docutils.utils import relative_path

from sphinx.deprecation import _old_jinja_template_suffix_warning
from sphinx.util.osutil import copyfile, ensuredir
from sphinx.util.typing import PathMatcher

if TYPE_CHECKING:
from sphinx.util.template import BaseRenderer


def _template_basename(filename: str) -> str | None:
"""Given an input filename:
If the input looks like a template, then return the filename output should
be written to. Otherwise, return no result (None)."""
# TODO: deprecate '_t' template suffix support after 2024-12-31
if filename.lower().endswith('_t'):
_old_jinja_template_suffix_warning(filename)
return filename[:-2]
elif filename.lower().endswith(".jinja"):
return filename[:-6]
return None
jayaddison marked this conversation as resolved.
Show resolved Hide resolved


def copy_asset_file(source: str, destination: str,
context: dict | None = None,
renderer: BaseRenderer | None = None) -> None:
Expand All @@ -35,14 +49,13 @@ def copy_asset_file(source: str, destination: str,
# Use source filename if destination points a directory
destination = os.path.join(destination, os.path.basename(source))

if source.lower().endswith('_t') and context is not None:
if _template_basename(source) and context is not None:
jayaddison marked this conversation as resolved.
Show resolved Hide resolved
if renderer is None:
from sphinx.util.template import SphinxRenderer
renderer = SphinxRenderer()

with open(source, encoding='utf-8') as fsrc:
if destination.lower().endswith('_t'):
destination = destination[:-2]
destination = _template_basename(destination) or destination
jayaddison marked this conversation as resolved.
Show resolved Hide resolved
with open(destination, 'w', encoding='utf-8') as fdst:
fdst.write(renderer.render_string(fsrc.read(), context))
else:
Expand Down