Skip to content

Commit 5d13215

Browse files
Support and prefer .jinja to _t for static templates (#11165)
Co-authored-by: Adam Turner <[email protected]>
1 parent f82c3c9 commit 5d13215

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+299
-60
lines changed

CHANGES

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ Deprecated
2323
----------
2424

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

2732
Features added
2833
--------------
@@ -60,6 +65,10 @@ Features added
6065
``= 'xelatex'``. Patch by Dimitar Dimitrov
6166
* #11109, #9643: Add :confval:`python_display_short_literal_types` option for
6267
condensed rendering of ``Literal`` types.
68+
* #11165: Support the `officially recommended`_ ``.jinja`` suffix for template
69+
files. Patch by James Addison
70+
71+
.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
6372

6473
Bugs fixed
6574
----------

doc/development/theming.rst

+42-4

doc/latex.rst

+4-4

sphinx/builders/_epub_base.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ def build_content(self) -> None:
603603
html.escape(self.refnodes[0]['refuri'])))
604604

605605
# write the project file
606-
copy_asset_file(path.join(self.template_dir, 'content.opf_t'), self.outdir, metadata)
606+
content_t = path.join(self.template_dir, 'content.opf.jinja')
607+
copy_asset_file(content_t, self.outdir, metadata)
607608

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

692693
def build_epub(self) -> None:

sphinx/builders/changes.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ def hl(no: int, line: str) -> str:
133133
f.write(self.templates.render('changes/rstsource.html', ctx))
134134
themectx = {'theme_' + key: val for (key, val) in
135135
self.theme.get_options({}).items()}
136-
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
137-
self.outdir, context=themectx, renderer=self.templates)
138-
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
139-
self.outdir)
136+
default_t = path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja')
137+
copy_asset_file(default_t, self.outdir, context=themectx, renderer=self.templates)
138+
basic = path.join(package_dir, 'themes', 'basic', 'static', 'basic.css')
139+
copy_asset_file(basic, self.outdir)
140140

141141
def hl(self, text: str, version: str) -> str:
142142
text = html.escape(text)

sphinx/builders/epub3.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def build_navigation_doc(self) -> None:
184184
# 'includehidden'
185185
refnodes = self.refnodes
186186
navlist = self.build_navlist(refnodes)
187-
copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'), self.outdir,
187+
copy_asset_file(path.join(self.template_dir, 'nav.xhtml.jinja'), self.outdir,
188188
self.navigation_doc_metadata(navlist))
189189

190190
# Add nav.xhtml to epub file

sphinx/builders/gettext.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def finish(self) -> None:
283283
ensuredir(path.join(self.outdir, path.dirname(textdomain)))
284284

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

288288
pofn = path.join(self.outdir, textdomain + '.pot')
289289
if should_write(pofn, content):

sphinx/builders/latex/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ def copy_support_files(self) -> None:
402402
# use pre-1.6.x Makefile for make latexpdf on Windows
403403
if os.name == 'nt':
404404
staticdirname = path.join(package_dir, 'texinputs_win')
405-
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
405+
copy_asset_file(path.join(staticdirname, 'Makefile.jinja'),
406406
self.outdir, context=context)
407407

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

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

447447

sphinx/cmd/quickstart.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -370,29 +370,29 @@ def write_file(fpath: str, content: str, newline: str | None = None) -> None:
370370
if 'quiet' not in d:
371371
print(__('File %s already exists, skipping.') % fpath)
372372

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

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

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

390390
if d.get('make_mode') is True:
391-
makefile_template = 'quickstart/Makefile.new_t'
392-
batchfile_template = 'quickstart/make.bat.new_t'
391+
makefile_template = 'quickstart/Makefile.new.jinja'
392+
batchfile_template = 'quickstart/make.bat.new.jinja'
393393
else:
394-
makefile_template = 'quickstart/Makefile_t'
395-
batchfile_template = 'quickstart/make.bat_t'
394+
makefile_template = 'quickstart/Makefile.jinja'
395+
batchfile_template = 'quickstart/make.bat.jinja'
396396

397397
if d['makefile'] is True:
398398
d['rsrcdir'] = 'source' if d['sep'] else '.'

sphinx/deprecation.py

+28
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,31 @@ def __getattr__(name):
6262

6363
warnings.warn(message + " Check CHANGES for Sphinx API modifications.",
6464
warning_class, stacklevel=3)
65+
66+
67+
class OldJinjaSuffixWarning(PendingDeprecationWarning):
68+
"""Warning class for ``_old_jinja_template_suffix_warning``.
69+
70+
This class exists only so that extensions and themes can silence the legacy
71+
filename warning via Python's `warning control`_ mechanisms. See
72+
:ref:`theming-static-templates` for an example.
73+
74+
This warning class will be removed, and the warning class changed to the
75+
appropriate RemovedInSphinx_0Warning no earlier than 31 December 2024, at
76+
which point the standard deprecation process for ``_t`` template suffixes
77+
will start.
78+
79+
.. _warning control: https://docs.python.org/3/library/warnings.html#the-warnings-filter
80+
"""
81+
82+
83+
def _old_jinja_template_suffix_warning(filename: str) -> None:
84+
if filename.endswith('_t'):
85+
warnings.warn(
86+
f"{filename!r}: the '_t' suffix for Jinja templates is deprecated. "
87+
"If the file is a template, use the suffix '.jinja' instead. "
88+
'For more information, see '
89+
'https://www.sphinx-doc.org/en/master/development/theming.html#static-templates',
90+
OldJinjaSuffixWarning,
91+
stacklevel=3,
92+
)

sphinx/ext/apidoc.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def create_module_file(package: str, basename: str, opts: Any,
102102
'qualname': qualname,
103103
'automodule_options': options,
104104
}
105-
text = ReSTRenderer([user_template_dir, template_dir]).render('module.rst_t', context)
105+
text = ReSTRenderer([user_template_dir, template_dir]).render('module.rst.jinja', context)
106106
write_file(qualname, text, opts)
107107

108108

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

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

169170

sphinx/ext/imgmath.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from sphinx.application import Sphinx
2020
from sphinx.builders import Builder
2121
from sphinx.config import Config
22+
from sphinx.deprecation import _old_jinja_template_suffix_warning
2223
from sphinx.errors import SphinxError
2324
from sphinx.locale import _, __
2425
from sphinx.util import logging, sha1
@@ -95,16 +96,20 @@ def generate_latex_macro(image_format: str,
9596
}
9697

9798
if config.imgmath_use_preview:
98-
template_name = 'preview.tex_t'
99+
template_name = 'preview.tex'
99100
else:
100-
template_name = 'template.tex_t'
101+
template_name = 'template.tex'
101102

102103
for template_dir in config.templates_path:
103-
template = path.join(confdir, template_dir, template_name)
104-
if path.exists(template):
105-
return LaTeXRenderer().render(template, variables)
106-
107-
return LaTeXRenderer(templates_path).render(template_name, variables)
104+
# TODO: deprecate '_t' template suffix support after 2024-12-31
105+
for template_suffix in ('_t', '.jinja'):
106+
template = path.join(confdir, template_dir, template_name + template_suffix)
107+
if path.exists(template):
108+
_old_jinja_template_suffix_warning(template)
109+
return LaTeXRenderer().render(template, variables)
110+
111+
# Default: fallback to a pathless in-library jinja template
112+
return LaTeXRenderer(templates_path).render(f"{template_name}.jinja", variables)
108113

109114

110115
def ensure_tempdir(builder: Builder) -> str:
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

sphinx/util/fileutil.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,27 @@
88

99
from docutils.utils import relative_path
1010

11+
from sphinx.deprecation import _old_jinja_template_suffix_warning
1112
from sphinx.util.osutil import copyfile, ensuredir
1213
from sphinx.util.typing import PathMatcher
1314

1415
if TYPE_CHECKING:
1516
from sphinx.util.template import BaseRenderer
1617

1718

19+
def _template_basename(filename: str) -> str | None:
20+
"""Given an input filename:
21+
If the input looks like a template, then return the filename output should
22+
be written to. Otherwise, return no result (None)."""
23+
# TODO: deprecate '_t' template suffix support after 2024-12-31
24+
if filename.lower().endswith('_t'):
25+
_old_jinja_template_suffix_warning(filename)
26+
return filename[:-2]
27+
elif filename.lower().endswith(".jinja"):
28+
return filename[:-6]
29+
return None
30+
31+
1832
def copy_asset_file(source: str, destination: str,
1933
context: dict | None = None,
2034
renderer: BaseRenderer | None = None) -> None:
@@ -35,14 +49,13 @@ def copy_asset_file(source: str, destination: str,
3549
# Use source filename if destination points a directory
3650
destination = os.path.join(destination, os.path.basename(source))
3751

38-
if source.lower().endswith('_t') and context is not None:
52+
if _template_basename(source) and context is not None:
3953
if renderer is None:
4054
from sphinx.util.template import SphinxRenderer
4155
renderer = SphinxRenderer()
4256

4357
with open(source, encoding='utf-8') as fsrc:
44-
if destination.lower().endswith('_t'):
45-
destination = destination[:-2]
58+
destination = _template_basename(destination) or destination
4659
with open(destination, 'w', encoding='utf-8') as fdst:
4760
fdst.write(renderer.render_string(fsrc.read(), context))
4861
else:

0 commit comments

Comments
 (0)