Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions doc/man/sphinx-apidoc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,15 @@ These options are used when :option:`--full` is specified:
sphinx project files generated by apidoc. Following Jinja2 template
files are allowed:

* ``module.rst_t``
* ``package.rst_t``
* ``toc.rst_t``
* ``root_doc.rst_t``
* ``conf.py_t``
* ``Makefile_t``
* ``Makefile.new_t``
* ``make.bat_t``
* ``make.bat.new_t``
* ``module.rst.jinja``
* ``package.rst.jinja``
* ``toc.rst.jinja``
* ``root_doc.rst.jinja``
* ``conf.py.jinja``
* ``Makefile.jinja``
* ``Makefile.new.jinja``
* ``make.bat.jinja``
* ``make.bat.new.jinja``

In detail, please refer the system template files Sphinx provides.
(``sphinx/templates/apidoc`` and ``sphinx/templates/quickstart``)
Expand Down
12 changes: 6 additions & 6 deletions doc/man/sphinx-quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ Options
sphinx project files generated by quickstart. Following Jinja2 template
files are allowed:

* ``root_doc.rst_t``
* ``conf.py_t``
* ``Makefile_t``
* ``Makefile.new_t``
* ``make.bat_t``
* ``make.bat.new_t``
* ``root_doc.rst.jinja``
* ``conf.py.jinja``
* ``Makefile.jinja``
* ``Makefile.new.jinja``
* ``make.bat.jinja``
* ``make.bat.new.jinja``

In detail, please refer the system template files Sphinx provides.
(``sphinx/templates/quickstart``)
Expand Down
4 changes: 2 additions & 2 deletions sphinx/builders/_epub_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ 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)
copy_asset_file(path.join(self.template_dir, 'content.opf.jinja'), self.outdir, metadata) # NoQA: E501

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 @@ -698,7 +698,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
2 changes: 1 addition & 1 deletion sphinx/builders/changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ 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'),
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja'), # NoQA: E501
self.outdir, context=themectx, renderer=self.templates)
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
self.outdir)
Expand Down
2 changes: 1 addition & 1 deletion sphinx/builders/epub3.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,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
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,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
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,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 @@ -456,7 +456,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
22 changes: 11 additions & 11 deletions sphinx/cmd/quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,32 +372,32 @@ 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'):
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.')
if template._has_custom_template('quickstart/master_doc.rst.jinja'):
msg = ('A custom template `master_doc.rst.jinja` found. It has been renamed to '
'`root_doc.rst.jinja`. 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'):
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:
# xref RemovedInSphinx80Warning
msg = "Support for '--no-use-make-mode' will be removed in Sphinx 8."
print(colorize('red', msg))
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
6 changes: 3 additions & 3 deletions sphinx/ext/apidoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def create_module_file(
template_path = [user_template_dir, template_dir]
else:
template_path = [template_dir]
text = ReSTRenderer(template_path).render('module.rst_t', context)
text = ReSTRenderer(template_path).render('module.rst.jinja', context)
return write_file(qualname, text, opts)


Expand Down Expand Up @@ -172,7 +172,7 @@ def create_package_file(

written: list[Path] = []

text = ReSTRenderer(template_path).render('package.rst_t', context)
text = ReSTRenderer(template_path).render('package.rst.jinja', context)
written.append(write_file(pkgname, text, opts))

if submodules and opts.separatemodules:
Expand Down Expand Up @@ -209,7 +209,7 @@ def create_modules_toc_file(
template_path = [user_template_dir, template_dir]
else:
template_path = [template_dir]
text = ReSTRenderer(template_path).render('toc.rst_t', context)
text = ReSTRenderer(template_path).render('toc.rst.jinja', context)
return write_file(name, text, opts)


Expand Down
13 changes: 7 additions & 6 deletions sphinx/ext/imgmath.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,17 @@ 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)
for template_suffix in ('_t', '.jinja'):
template = path.join(confdir, template_dir, template_name + template_suffix)
if path.exists(template):
return LaTeXRenderer().render(template, variables)

return LaTeXRenderer(templates_path).render(template_name, variables)
return LaTeXRenderer(templates_path).render(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.
8 changes: 6 additions & 2 deletions sphinx/writers/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def astext(self) -> str:
'body': ''.join(self.body),
'indices': self.generate_indices(),
})
return self.render('latex.tex_t', self.elements)
return self.render('latex.tex.jinja', self.elements)

def hypertarget(self, id: str, withdoc: bool = True, anchor: bool = True) -> str:
if withdoc:
Expand Down Expand Up @@ -521,6 +521,10 @@ def render(self, template_name: str, variables: dict[str, Any]) -> str:
template_name)
if path.exists(template):
return renderer.render(template, variables)
elif template_name.endswith('.jinja'):
legacy_template = template[:-len('.jinja')] + '_t'
if path.exists(legacy_template):
return renderer.render(legacy_template, variables)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This legacy loading path logic that I switched in isn't something I'm 100% keen on - it's non-obvious enough to feel a bit ugly behaviour-wise.

I think I'll add a warning message when this legacy path is followed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also a search precedence question here; do we search all template paths for the .jinja file and then all paths for _t, or do we (as currently implemented) perform a single pass through the template paths and check for both file variants.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically I'm worrying about a security-type concern here: it's that someone could place a _t (legacy) file in a template path that they control, and that this logic would then load then instead of the expected .jinja file.

However: I'm not sure that that particular concern is well-founded, because if an attacker has write access to one of the template paths already, they could equally just write a .jinja file in there, and that would achieve the same effect.

However I do think a warning message would still add some value as it could help people to encourage legacy templates to migrate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that I'm considering the security concern a non-issue, I think that the file-load-order precedence is less important here, and it is OK to use a logically-simpler single search pass over the template paths.


return renderer.render(template_name, variables)

Expand Down Expand Up @@ -1033,7 +1037,7 @@ def depart_table(self, node: Element) -> None:
assert self.table is not None
labels = self.hypertarget_to(node)
table_type = self.table.get_table_type()
table = self.render(table_type + '.tex_t',
table = self.render(table_type + '.tex.jinja',
{'table': self.table, 'labels': labels})
self.body.append(BLANKLINE)
self.body.append(table)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_builders/test_build_html_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_html_assets(app):
# html_extra_path
assert (app.outdir / '.htaccess').exists()
assert not (app.outdir / '.htpasswd').exists()
assert (app.outdir / 'API.html_t').exists()
assert (app.outdir / 'API.html.jinja').exists()
assert (app.outdir / 'css/style.css').exists()
assert (app.outdir / 'rimg.png').exists()
assert not (app.outdir / '_build' / 'index.html').exists()
Expand Down
16 changes: 8 additions & 8 deletions tests/test_util/test_util_fileutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ def test_copy_asset_file(tmp_path):
assert src.read_text(encoding='utf8') == dest.read_text(encoding='utf8')

# copy template file
src = (tmp_path / 'asset.txt_t')
src = (tmp_path / 'asset.txt.jinja')
src.write_text('# {{var1}} data', encoding='utf8')
dest = (tmp_path / 'output.txt_t')
dest = (tmp_path / 'output.txt.jinja')

copy_asset_file(str(src), str(dest), {'var1': 'template'}, renderer)
assert not dest.exists()
assert (tmp_path / 'output.txt').exists()
assert (tmp_path / 'output.txt').read_text(encoding='utf8') == '# template data'

# copy template file to subdir
src = (tmp_path / 'asset.txt_t')
src = (tmp_path / 'asset.txt.jinja')
src.write_text('# {{var1}} data', encoding='utf8')
subdir1 = (tmp_path / 'subdir')
subdir1.mkdir(parents=True, exist_ok=True)
Expand All @@ -48,14 +48,14 @@ def test_copy_asset_file(tmp_path):
assert (subdir1 / 'asset.txt').read_text(encoding='utf8') == '# template data'

# copy template file without context
src = (tmp_path / 'asset.txt_t')
src = (tmp_path / 'asset.txt.jinja')
subdir2 = (tmp_path / 'subdir2')
subdir2.mkdir(parents=True, exist_ok=True)

copy_asset_file(src, subdir2)
assert not (subdir2 / 'asset.txt').exists()
assert (subdir2 / 'asset.txt_t').exists()
assert (subdir2 / 'asset.txt_t').read_text(encoding='utf8') == '# {{var1}} data'
assert (subdir2 / 'asset.txt.jinja').exists()
assert (subdir2 / 'asset.txt.jinja').read_text(encoding='utf8') == '# {{var1}} data'


def test_copy_asset(tmp_path):
Expand All @@ -65,12 +65,12 @@ def test_copy_asset(tmp_path):
source = (tmp_path / 'source')
source.mkdir(parents=True, exist_ok=True)
(source / 'index.rst').write_text('index.rst', encoding='utf8')
(source / 'foo.rst_t').write_text('{{var1}}.rst', encoding='utf8')
(source / 'foo.rst.jinja').write_text('{{var1}}.rst', encoding='utf8')
(source / '_static').mkdir(parents=True, exist_ok=True)
(source / '_static' / 'basic.css').write_text('basic.css', encoding='utf8')
(source / '_templates').mkdir(parents=True, exist_ok=True)
(source / '_templates' / 'layout.html').write_text('layout.html', encoding='utf8')
(source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}', encoding='utf8')
(source / '_templates' / 'sidebar.html.jinja').write_text('sidebar: {{var2}}', encoding='utf8')

# copy a single file
assert not (tmp_path / 'test1').exists()
Expand Down