From 5d13215b58f93c6be8255ef2e3e20836508c7d47 Mon Sep 17 00:00:00 2001 From: James Addison <55152140+jayaddison@users.noreply.github.com> Date: Fri, 7 Apr 2023 18:07:15 +0100 Subject: [PATCH] Support and prefer ``.jinja`` to ``_t`` for static templates (#11165) Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- CHANGES | 9 ++ doc/development/theming.rst | 46 ++++++- doc/latex.rst | 8 +- sphinx/builders/_epub_base.py | 5 +- sphinx/builders/changes.py | 8 +- sphinx/builders/epub3.py | 2 +- sphinx/builders/gettext.py | 2 +- sphinx/builders/latex/__init__.py | 4 +- sphinx/cmd/quickstart.py | 18 +-- sphinx/deprecation.py | 28 +++++ sphinx/ext/apidoc.py | 7 +- sphinx/ext/imgmath.py | 19 +-- .../apidoc/{module.rst_t => module.rst.jinja} | 0 .../{package.rst_t => package.rst.jinja} | 0 .../apidoc/{toc.rst_t => toc.rst.jinja} | 0 .../{content.opf_t => content.opf.jinja} | 0 .../epub3/{nav.xhtml_t => nav.xhtml.jinja} | 0 .../epub3/{toc.ncx_t => toc.ncx.jinja} | 0 .../{message.pot_t => message.pot.jinja} | 0 .../{preview.tex_t => preview.tex.jinja} | 0 .../{template.tex_t => template.tex.jinja} | 0 .../latex/{latex.tex_t => latex.tex.jinja} | 0 .../{longtable.tex_t => longtable.tex.jinja} | 0 ...essages.sty_t => sphinxmessages.sty.jinja} | 0 .../{tabular.tex_t => tabular.tex.jinja} | 0 .../{tabulary.tex_t => tabulary.tex.jinja} | 0 .../quickstart/{Makefile_t => Makefile.jinja} | 0 .../{Makefile.new_t => Makefile.new.jinja} | 0 .../quickstart/{conf.py_t => conf.py.jinja} | 0 .../quickstart/{make.bat_t => make.bat.jinja} | 0 .../{make.bat.new_t => make.bat.new.jinja} | 0 .../{root_doc.rst_t => root_doc.rst.jinja} | 0 .../texinputs/{Makefile_t => Makefile.jinja} | 0 .../{latexmkjarc_t => latexmkjarc.jinja} | 0 .../{latexmkrc_t => latexmkrc.jinja} | 0 .../texinputs/{make.bat_t => make.bat.jinja} | 0 .../{Makefile_t => Makefile.jinja} | 0 .../static/{agogo.css_t => agogo.css.jinja} | 0 .../static/{basic.css_t => basic.css.jinja} | 0 ...ns.js_t => documentation_options.js.jinja} | 0 ...guage_data.js_t => language_data.js.jinja} | 0 .../{bizstyle.css_t => bizstyle.css.jinja} | 0 .../{bizstyle.js_t => bizstyle.js.jinja} | 0 .../{classic.css_t => classic.css.jinja} | 0 .../static/{sidebar.js_t => sidebar.js.jinja} | 0 .../static/{epub.css_t => epub.css.jinja} | 0 .../static/{haiku.css_t => haiku.css.jinja} | 0 .../static/{nature.css_t => nature.css.jinja} | 0 .../static/{nonav.css_t => nonav.css.jinja} | 0 .../static/{epub.css_t => epub.css.jinja} | 0 .../{pyramid.css_t => pyramid.css.jinja} | 0 .../{scrolls.css_t => scrolls.css.jinja} | 0 .../{sphinxdoc.css_t => sphinxdoc.css.jinja} | 0 ...raditional.css_t => traditional.css.jinja} | 0 sphinx/util/fileutil.py | 19 ++- sphinx/writers/latex.py | 28 +++-- .../extra/{API.html_t => API.html.jinja} | 0 .../static/{API.html_t => API.html.jinja} | 0 .../{longtable.tex_t => longtable.tex.jinja} | 0 .../_mytemplates/latex/tabulary.tex_t | 2 + ...tatictmpl.html_t => statictmpl.html.jinja} | 0 tests/test_build_html.py | 2 +- tests/test_build_latex.py | 4 + tests/test_deprecation.py | 114 ++++++++++++++++++ tests/test_util_fileutil.py | 29 +++-- utils/babel_runner.py | 5 + 66 files changed, 299 insertions(+), 60 deletions(-) rename sphinx/templates/apidoc/{module.rst_t => module.rst.jinja} (100%) rename sphinx/templates/apidoc/{package.rst_t => package.rst.jinja} (100%) rename sphinx/templates/apidoc/{toc.rst_t => toc.rst.jinja} (100%) rename sphinx/templates/epub3/{content.opf_t => content.opf.jinja} (100%) rename sphinx/templates/epub3/{nav.xhtml_t => nav.xhtml.jinja} (100%) rename sphinx/templates/epub3/{toc.ncx_t => toc.ncx.jinja} (100%) rename sphinx/templates/gettext/{message.pot_t => message.pot.jinja} (100%) rename sphinx/templates/imgmath/{preview.tex_t => preview.tex.jinja} (100%) rename sphinx/templates/imgmath/{template.tex_t => template.tex.jinja} (100%) rename sphinx/templates/latex/{latex.tex_t => latex.tex.jinja} (100%) rename sphinx/templates/latex/{longtable.tex_t => longtable.tex.jinja} (100%) rename sphinx/templates/latex/{sphinxmessages.sty_t => sphinxmessages.sty.jinja} (100%) rename sphinx/templates/latex/{tabular.tex_t => tabular.tex.jinja} (100%) rename sphinx/templates/latex/{tabulary.tex_t => tabulary.tex.jinja} (100%) rename sphinx/templates/quickstart/{Makefile_t => Makefile.jinja} (100%) rename sphinx/templates/quickstart/{Makefile.new_t => Makefile.new.jinja} (100%) rename sphinx/templates/quickstart/{conf.py_t => conf.py.jinja} (100%) rename sphinx/templates/quickstart/{make.bat_t => make.bat.jinja} (100%) rename sphinx/templates/quickstart/{make.bat.new_t => make.bat.new.jinja} (100%) rename sphinx/templates/quickstart/{root_doc.rst_t => root_doc.rst.jinja} (100%) rename sphinx/texinputs/{Makefile_t => Makefile.jinja} (100%) rename sphinx/texinputs/{latexmkjarc_t => latexmkjarc.jinja} (100%) rename sphinx/texinputs/{latexmkrc_t => latexmkrc.jinja} (100%) rename sphinx/texinputs/{make.bat_t => make.bat.jinja} (100%) rename sphinx/texinputs_win/{Makefile_t => Makefile.jinja} (100%) rename sphinx/themes/agogo/static/{agogo.css_t => agogo.css.jinja} (100%) rename sphinx/themes/basic/static/{basic.css_t => basic.css.jinja} (100%) rename sphinx/themes/basic/static/{documentation_options.js_t => documentation_options.js.jinja} (100%) rename sphinx/themes/basic/static/{language_data.js_t => language_data.js.jinja} (100%) rename sphinx/themes/bizstyle/static/{bizstyle.css_t => bizstyle.css.jinja} (100%) rename sphinx/themes/bizstyle/static/{bizstyle.js_t => bizstyle.js.jinja} (100%) rename sphinx/themes/classic/static/{classic.css_t => classic.css.jinja} (100%) rename sphinx/themes/classic/static/{sidebar.js_t => sidebar.js.jinja} (100%) rename sphinx/themes/epub/static/{epub.css_t => epub.css.jinja} (100%) rename sphinx/themes/haiku/static/{haiku.css_t => haiku.css.jinja} (100%) rename sphinx/themes/nature/static/{nature.css_t => nature.css.jinja} (100%) rename sphinx/themes/nonav/static/{nonav.css_t => nonav.css.jinja} (100%) rename sphinx/themes/pyramid/static/{epub.css_t => epub.css.jinja} (100%) rename sphinx/themes/pyramid/static/{pyramid.css_t => pyramid.css.jinja} (100%) rename sphinx/themes/scrolls/static/{scrolls.css_t => scrolls.css.jinja} (100%) rename sphinx/themes/sphinxdoc/static/{sphinxdoc.css_t => sphinxdoc.css.jinja} (100%) rename sphinx/themes/traditional/static/{traditional.css_t => traditional.css.jinja} (100%) rename tests/roots/test-html_assets/extra/{API.html_t => API.html.jinja} (100%) rename tests/roots/test-html_assets/static/{API.html_t => API.html.jinja} (100%) rename tests/roots/test-latex-table/_mytemplates/latex/{longtable.tex_t => longtable.tex.jinja} (100%) create mode 100644 tests/roots/test-latex-table/_mytemplates/latex/tabulary.tex_t rename tests/roots/test-theming/test_theme/staticfiles/static/{statictmpl.html_t => statictmpl.html.jinja} (100%) create mode 100644 tests/test_deprecation.py diff --git a/CHANGES b/CHANGES index a66c2c46039..8a77524fe4d 100644 --- a/CHANGES +++ b/CHANGES @@ -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 -------------- @@ -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 ---------- diff --git a/doc/development/theming.rst b/doc/development/theming.rst index 3a156fa4f5a..65216787f70 100644 --- a/doc/development/theming.rst +++ b/doc/development/theming.rst @@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/latex.rst b/doc/latex.rst index 1a9f6a2ec4c..e82ff1060d3 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -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). .. versionadded:: 1.6 currently all template variables are unstable and undocumented. diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py index dfe4877ec81..f06ff520bc1 100644 --- a/sphinx/builders/_epub_base.py +++ b/sphinx/builders/_epub_base.py @@ -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.""" @@ -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: diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py index 5c118bef933..f6b9152f9cf 100644 --- a/sphinx/builders/changes.py +++ b/sphinx/builders/changes.py @@ -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) diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py index 03f4684d147..aaae0bcee7e 100644 --- a/sphinx/builders/epub3.py +++ b/sphinx/builders/epub3.py @@ -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 diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 4d460109b30..414ed50bd50 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -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): diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index f1f0cff2be4..b8472a3c0e9 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -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')) @@ -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()) diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index 6122ddd9890..580fa7d6d50 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -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 '.' diff --git a/sphinx/deprecation.py b/sphinx/deprecation.py index fbd5463cce3..7d5a2d2abab 100644 --- a/sphinx/deprecation.py +++ b/sphinx/deprecation.py @@ -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, + ) diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index 108515d7363..9c9336075fa 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -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) @@ -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: @@ -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) diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index 34d716686d3..975cbcca540 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -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 @@ -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: diff --git a/sphinx/templates/apidoc/module.rst_t b/sphinx/templates/apidoc/module.rst.jinja similarity index 100% rename from sphinx/templates/apidoc/module.rst_t rename to sphinx/templates/apidoc/module.rst.jinja diff --git a/sphinx/templates/apidoc/package.rst_t b/sphinx/templates/apidoc/package.rst.jinja similarity index 100% rename from sphinx/templates/apidoc/package.rst_t rename to sphinx/templates/apidoc/package.rst.jinja diff --git a/sphinx/templates/apidoc/toc.rst_t b/sphinx/templates/apidoc/toc.rst.jinja similarity index 100% rename from sphinx/templates/apidoc/toc.rst_t rename to sphinx/templates/apidoc/toc.rst.jinja diff --git a/sphinx/templates/epub3/content.opf_t b/sphinx/templates/epub3/content.opf.jinja similarity index 100% rename from sphinx/templates/epub3/content.opf_t rename to sphinx/templates/epub3/content.opf.jinja diff --git a/sphinx/templates/epub3/nav.xhtml_t b/sphinx/templates/epub3/nav.xhtml.jinja similarity index 100% rename from sphinx/templates/epub3/nav.xhtml_t rename to sphinx/templates/epub3/nav.xhtml.jinja diff --git a/sphinx/templates/epub3/toc.ncx_t b/sphinx/templates/epub3/toc.ncx.jinja similarity index 100% rename from sphinx/templates/epub3/toc.ncx_t rename to sphinx/templates/epub3/toc.ncx.jinja diff --git a/sphinx/templates/gettext/message.pot_t b/sphinx/templates/gettext/message.pot.jinja similarity index 100% rename from sphinx/templates/gettext/message.pot_t rename to sphinx/templates/gettext/message.pot.jinja diff --git a/sphinx/templates/imgmath/preview.tex_t b/sphinx/templates/imgmath/preview.tex.jinja similarity index 100% rename from sphinx/templates/imgmath/preview.tex_t rename to sphinx/templates/imgmath/preview.tex.jinja diff --git a/sphinx/templates/imgmath/template.tex_t b/sphinx/templates/imgmath/template.tex.jinja similarity index 100% rename from sphinx/templates/imgmath/template.tex_t rename to sphinx/templates/imgmath/template.tex.jinja diff --git a/sphinx/templates/latex/latex.tex_t b/sphinx/templates/latex/latex.tex.jinja similarity index 100% rename from sphinx/templates/latex/latex.tex_t rename to sphinx/templates/latex/latex.tex.jinja diff --git a/sphinx/templates/latex/longtable.tex_t b/sphinx/templates/latex/longtable.tex.jinja similarity index 100% rename from sphinx/templates/latex/longtable.tex_t rename to sphinx/templates/latex/longtable.tex.jinja diff --git a/sphinx/templates/latex/sphinxmessages.sty_t b/sphinx/templates/latex/sphinxmessages.sty.jinja similarity index 100% rename from sphinx/templates/latex/sphinxmessages.sty_t rename to sphinx/templates/latex/sphinxmessages.sty.jinja diff --git a/sphinx/templates/latex/tabular.tex_t b/sphinx/templates/latex/tabular.tex.jinja similarity index 100% rename from sphinx/templates/latex/tabular.tex_t rename to sphinx/templates/latex/tabular.tex.jinja diff --git a/sphinx/templates/latex/tabulary.tex_t b/sphinx/templates/latex/tabulary.tex.jinja similarity index 100% rename from sphinx/templates/latex/tabulary.tex_t rename to sphinx/templates/latex/tabulary.tex.jinja diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile.jinja similarity index 100% rename from sphinx/templates/quickstart/Makefile_t rename to sphinx/templates/quickstart/Makefile.jinja diff --git a/sphinx/templates/quickstart/Makefile.new_t b/sphinx/templates/quickstart/Makefile.new.jinja similarity index 100% rename from sphinx/templates/quickstart/Makefile.new_t rename to sphinx/templates/quickstart/Makefile.new.jinja diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py.jinja similarity index 100% rename from sphinx/templates/quickstart/conf.py_t rename to sphinx/templates/quickstart/conf.py.jinja diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat.jinja similarity index 100% rename from sphinx/templates/quickstart/make.bat_t rename to sphinx/templates/quickstart/make.bat.jinja diff --git a/sphinx/templates/quickstart/make.bat.new_t b/sphinx/templates/quickstart/make.bat.new.jinja similarity index 100% rename from sphinx/templates/quickstart/make.bat.new_t rename to sphinx/templates/quickstart/make.bat.new.jinja diff --git a/sphinx/templates/quickstart/root_doc.rst_t b/sphinx/templates/quickstart/root_doc.rst.jinja similarity index 100% rename from sphinx/templates/quickstart/root_doc.rst_t rename to sphinx/templates/quickstart/root_doc.rst.jinja diff --git a/sphinx/texinputs/Makefile_t b/sphinx/texinputs/Makefile.jinja similarity index 100% rename from sphinx/texinputs/Makefile_t rename to sphinx/texinputs/Makefile.jinja diff --git a/sphinx/texinputs/latexmkjarc_t b/sphinx/texinputs/latexmkjarc.jinja similarity index 100% rename from sphinx/texinputs/latexmkjarc_t rename to sphinx/texinputs/latexmkjarc.jinja diff --git a/sphinx/texinputs/latexmkrc_t b/sphinx/texinputs/latexmkrc.jinja similarity index 100% rename from sphinx/texinputs/latexmkrc_t rename to sphinx/texinputs/latexmkrc.jinja diff --git a/sphinx/texinputs/make.bat_t b/sphinx/texinputs/make.bat.jinja similarity index 100% rename from sphinx/texinputs/make.bat_t rename to sphinx/texinputs/make.bat.jinja diff --git a/sphinx/texinputs_win/Makefile_t b/sphinx/texinputs_win/Makefile.jinja similarity index 100% rename from sphinx/texinputs_win/Makefile_t rename to sphinx/texinputs_win/Makefile.jinja diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css.jinja similarity index 100% rename from sphinx/themes/agogo/static/agogo.css_t rename to sphinx/themes/agogo/static/agogo.css.jinja diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css.jinja similarity index 100% rename from sphinx/themes/basic/static/basic.css_t rename to sphinx/themes/basic/static/basic.css.jinja diff --git a/sphinx/themes/basic/static/documentation_options.js_t b/sphinx/themes/basic/static/documentation_options.js.jinja similarity index 100% rename from sphinx/themes/basic/static/documentation_options.js_t rename to sphinx/themes/basic/static/documentation_options.js.jinja diff --git a/sphinx/themes/basic/static/language_data.js_t b/sphinx/themes/basic/static/language_data.js.jinja similarity index 100% rename from sphinx/themes/basic/static/language_data.js_t rename to sphinx/themes/basic/static/language_data.js.jinja diff --git a/sphinx/themes/bizstyle/static/bizstyle.css_t b/sphinx/themes/bizstyle/static/bizstyle.css.jinja similarity index 100% rename from sphinx/themes/bizstyle/static/bizstyle.css_t rename to sphinx/themes/bizstyle/static/bizstyle.css.jinja diff --git a/sphinx/themes/bizstyle/static/bizstyle.js_t b/sphinx/themes/bizstyle/static/bizstyle.js.jinja similarity index 100% rename from sphinx/themes/bizstyle/static/bizstyle.js_t rename to sphinx/themes/bizstyle/static/bizstyle.js.jinja diff --git a/sphinx/themes/classic/static/classic.css_t b/sphinx/themes/classic/static/classic.css.jinja similarity index 100% rename from sphinx/themes/classic/static/classic.css_t rename to sphinx/themes/classic/static/classic.css.jinja diff --git a/sphinx/themes/classic/static/sidebar.js_t b/sphinx/themes/classic/static/sidebar.js.jinja similarity index 100% rename from sphinx/themes/classic/static/sidebar.js_t rename to sphinx/themes/classic/static/sidebar.js.jinja diff --git a/sphinx/themes/epub/static/epub.css_t b/sphinx/themes/epub/static/epub.css.jinja similarity index 100% rename from sphinx/themes/epub/static/epub.css_t rename to sphinx/themes/epub/static/epub.css.jinja diff --git a/sphinx/themes/haiku/static/haiku.css_t b/sphinx/themes/haiku/static/haiku.css.jinja similarity index 100% rename from sphinx/themes/haiku/static/haiku.css_t rename to sphinx/themes/haiku/static/haiku.css.jinja diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css.jinja similarity index 100% rename from sphinx/themes/nature/static/nature.css_t rename to sphinx/themes/nature/static/nature.css.jinja diff --git a/sphinx/themes/nonav/static/nonav.css_t b/sphinx/themes/nonav/static/nonav.css.jinja similarity index 100% rename from sphinx/themes/nonav/static/nonav.css_t rename to sphinx/themes/nonav/static/nonav.css.jinja diff --git a/sphinx/themes/pyramid/static/epub.css_t b/sphinx/themes/pyramid/static/epub.css.jinja similarity index 100% rename from sphinx/themes/pyramid/static/epub.css_t rename to sphinx/themes/pyramid/static/epub.css.jinja diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css.jinja similarity index 100% rename from sphinx/themes/pyramid/static/pyramid.css_t rename to sphinx/themes/pyramid/static/pyramid.css.jinja diff --git a/sphinx/themes/scrolls/static/scrolls.css_t b/sphinx/themes/scrolls/static/scrolls.css.jinja similarity index 100% rename from sphinx/themes/scrolls/static/scrolls.css_t rename to sphinx/themes/scrolls/static/scrolls.css.jinja diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css.jinja similarity index 100% rename from sphinx/themes/sphinxdoc/static/sphinxdoc.css_t rename to sphinx/themes/sphinxdoc/static/sphinxdoc.css.jinja diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css.jinja similarity index 100% rename from sphinx/themes/traditional/static/traditional.css_t rename to sphinx/themes/traditional/static/traditional.css.jinja diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py index 03928710e88..4185fb24635 100644 --- a/sphinx/util/fileutil.py +++ b/sphinx/util/fileutil.py @@ -8,6 +8,7 @@ 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 @@ -15,6 +16,19 @@ 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 + + def copy_asset_file(source: str, destination: str, context: dict | None = None, renderer: BaseRenderer | None = None) -> None: @@ -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: 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 with open(destination, 'w', encoding='utf-8') as fdst: fdst.write(renderer.render_string(fsrc.read(), context)) else: diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index e50b11b4f29..215fd4c765e 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -16,7 +16,7 @@ from docutils.nodes import Element, Node, Text from sphinx import addnodes, highlighting -from sphinx.deprecation import RemovedInSphinx70Warning +from sphinx.deprecation import RemovedInSphinx70Warning, _old_jinja_template_suffix_warning from sphinx.domains import IndexEntry from sphinx.domains.std import StandardDomain from sphinx.errors import SphinxError @@ -435,7 +435,8 @@ def astext(self) -> str: 'body': ''.join(self.body), 'indices': self.generate_indices(), }) - return self.render('latex.tex_t', self.elements) + template = self._find_template('latex.tex') + return self.render(template, self.elements) def hypertarget(self, id: str, withdoc: bool = True, anchor: bool = True) -> str: if withdoc: @@ -512,14 +513,21 @@ def generate(content: list[tuple[str, list[IndexEntry]]], collapsed: bool) -> No return ''.join(ret) - def render(self, template_name: str, variables: dict[str, Any]) -> str: - renderer = LaTeXRenderer(latex_engine=self.config.latex_engine) + def _find_template(self, template_name: str) -> str: for template_dir in self.config.templates_path: - template = path.join(self.builder.confdir, template_dir, - template_name) - if path.exists(template): - return renderer.render(template, variables) + # TODO: deprecate '_t' template suffix support after 2024-12-31 + for template_suffix in ('_t', '.jinja'): + template = path.join(self.builder.confdir, template_dir, + template_name + template_suffix) + if path.exists(template): + _old_jinja_template_suffix_warning(template) + return template + + # Default: fallback to a pathless in-library jinja template + return f"{template_name}.jinja" + def render(self, template_name: str, variables: dict[str, Any]) -> str: + renderer = LaTeXRenderer(latex_engine=self.config.latex_engine) return renderer.render(template_name, variables) @property @@ -902,8 +910,8 @@ def visit_table(self, node: Element) -> None: def depart_table(self, node: Element) -> None: labels = self.hypertarget_to(node) table_type = self.table.get_table_type() - table = self.render(table_type + '.tex_t', - {'table': self.table, 'labels': labels}) + template = self._find_template(f"{table_type}.tex") + table = self.render(template, {'table': self.table, 'labels': labels}) self.body.append(BLANKLINE) self.body.append(table) self.body.append(CR) diff --git a/tests/roots/test-html_assets/extra/API.html_t b/tests/roots/test-html_assets/extra/API.html.jinja similarity index 100% rename from tests/roots/test-html_assets/extra/API.html_t rename to tests/roots/test-html_assets/extra/API.html.jinja diff --git a/tests/roots/test-html_assets/static/API.html_t b/tests/roots/test-html_assets/static/API.html.jinja similarity index 100% rename from tests/roots/test-html_assets/static/API.html_t rename to tests/roots/test-html_assets/static/API.html.jinja diff --git a/tests/roots/test-latex-table/_mytemplates/latex/longtable.tex_t b/tests/roots/test-latex-table/_mytemplates/latex/longtable.tex.jinja similarity index 100% rename from tests/roots/test-latex-table/_mytemplates/latex/longtable.tex_t rename to tests/roots/test-latex-table/_mytemplates/latex/longtable.tex.jinja diff --git a/tests/roots/test-latex-table/_mytemplates/latex/tabulary.tex_t b/tests/roots/test-latex-table/_mytemplates/latex/tabulary.tex_t new file mode 100644 index 00000000000..c7afd28c539 --- /dev/null +++ b/tests/roots/test-latex-table/_mytemplates/latex/tabulary.tex_t @@ -0,0 +1,2 @@ +<# TODO: deprecate '_t' template suffix support after 2024-12-31 #> +AU REVOIR, KANIGGETS diff --git a/tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html_t b/tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html.jinja similarity index 100% rename from tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html_t rename to tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html.jinja diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 013c09bdb67..c5c84f8b139 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1153,7 +1153,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() diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index e39ac303cdf..5dce900e2a8 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -1379,6 +1379,10 @@ def test_latex_table_custom_template_caseA(app, status, warning): result = (app.outdir / 'python.tex').read_text(encoding='utf8') assert 'SALUT LES COPAINS' in result + # # TODO: deprecate '_t' template suffix support after 2024-12-31 + assert 'TODO' not in result + assert 'AU REVOIR, KANIGGETS' in result + @pytest.mark.sphinx('latex', testroot='latex-table', confoverrides={'templates_path': ['_mytemplates']}) diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py new file mode 100644 index 00000000000..77a4af7311b --- /dev/null +++ b/tests/test_deprecation.py @@ -0,0 +1,114 @@ +import warnings +from pathlib import Path + +import pytest + +from sphinx import deprecation + + +def test_old_jinja_suffix_warning_is_warning(): + assert isinstance(deprecation.OldJinjaSuffixWarning, type) + assert issubclass(deprecation.OldJinjaSuffixWarning, Warning) + assert issubclass(deprecation.OldJinjaSuffixWarning, PendingDeprecationWarning) + + with pytest.warns(deprecation.OldJinjaSuffixWarning): + warnings.warn('test_1', category=deprecation.OldJinjaSuffixWarning) + + with pytest.warns(PendingDeprecationWarning): + warnings.warn('test_2', category=deprecation.OldJinjaSuffixWarning) + + with pytest.warns(Warning): + warnings.warn('test_3', category=deprecation.OldJinjaSuffixWarning) + + +def test_old_jinja_suffix_warning_simplefilter_always(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + + warnings.simplefilter('always', category=deprecation.OldJinjaSuffixWarning) + warnings.warn('test_simplefilter_always', category=deprecation.OldJinjaSuffixWarning) + + assert len(recwarn) == 1 + caught_warning = recwarn[0] + assert caught_warning.category is deprecation.OldJinjaSuffixWarning + assert str(caught_warning.message) == 'test_simplefilter_always' + + +def test_old_jinja_suffix_warning_filterwarnings_always(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + + warnings.filterwarnings('always', category=deprecation.OldJinjaSuffixWarning) + warnings.warn('test_filterwarnings_always', category=deprecation.OldJinjaSuffixWarning) + + assert len(recwarn) == 1 + caught_warning = recwarn[0] + assert caught_warning.category is deprecation.OldJinjaSuffixWarning + assert str(caught_warning.message) == 'test_filterwarnings_always' + + +def test_old_jinja_suffix_warning_simplefilter_ignore(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + + warnings.simplefilter('ignore', deprecation.OldJinjaSuffixWarning) + warnings.warn('test_simplefilter_ignore', category=deprecation.OldJinjaSuffixWarning) + + assert len(recwarn) == 0 + + +def test_old_jinja_suffix_warning_filterwarnings_ignore(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + + warnings.filterwarnings('ignore', category=deprecation.OldJinjaSuffixWarning) + warnings.warn('test_filterwarnings_ignore', category=deprecation.OldJinjaSuffixWarning) + + assert len(recwarn) == 0 + + +def test__old_jinja_template_suffix_no_warning_css(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + warnings.simplefilter('always', category=deprecation.OldJinjaSuffixWarning) + + deprecation._old_jinja_template_suffix_warning('template.css') + + assert len(recwarn) == 0 + + +def test__old_jinja_template_suffix_no_warning_jinja(recwarn): + assert len(recwarn) == 0 + warnings.resetwarnings() + warnings.simplefilter('always', category=deprecation.OldJinjaSuffixWarning) + + deprecation._old_jinja_template_suffix_warning('template.css.jinja') + + assert len(recwarn) == 0 + + +def test__old_jinja_template_suffix_warning__t(): + with pytest.warns(deprecation.OldJinjaSuffixWarning, + match=r"the '_t' suffix for Jinja templates is deprecated"): + deprecation._old_jinja_template_suffix_warning('template.css_t') + + +def test__old_jinja_template_suffix_warning_stacklevel(): + # _old_jinja_template_suffix_warning is only called within functions that + # use template files. + def do_something_with_templates(filename): + deprecation._old_jinja_template_suffix_warning(filename) + + # TOJTSWS line number marker + with pytest.warns(deprecation.OldJinjaSuffixWarning) as caught: + do_something_with_templates('template.css_t') + + lines = [b''] + Path(__file__).read_bytes().splitlines() + line_number = lines.index(b' # TOJTSWS line number marker') + 2 + + assert len(caught) == 1 + caught_warning = caught[0] + assert caught_warning.category is deprecation.OldJinjaSuffixWarning + assert "the '_t' suffix for Jinja templates is deprecated" in str(caught_warning.message) + assert caught_warning.filename == __file__ + assert caught_warning.lineno == line_number diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py index 7ea12508c61..86f2c96b4e0 100644 --- a/tests/test_util_fileutil.py +++ b/tests/test_util_fileutil.py @@ -3,7 +3,7 @@ from unittest import mock from sphinx.jinja2glue import BuiltinTemplateLoader -from sphinx.util.fileutil import copy_asset, copy_asset_file +from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file class DummyTemplateLoader(BuiltinTemplateLoader): @@ -28,9 +28,9 @@ def test_copy_asset_file(tempdir): assert src.read_text(encoding='utf8') == dest.read_text(encoding='utf8') # copy template file - src = (tempdir / 'asset.txt_t') + src = (tempdir / 'asset.txt.jinja') src.write_text('# {{var1}} data') - dest = (tempdir / 'output.txt_t') + dest = (tempdir / 'output.txt.jinja') copy_asset_file(src, dest, {'var1': 'template'}, renderer) assert not dest.exists() @@ -38,7 +38,7 @@ def test_copy_asset_file(tempdir): assert (tempdir / 'output.txt').read_text(encoding='utf8') == '# template data' # copy template file to subdir - src = (tempdir / 'asset.txt_t') + src = (tempdir / 'asset.txt.jinja') src.write_text('# {{var1}} data') subdir1 = (tempdir / 'subdir') subdir1.makedirs() @@ -48,14 +48,14 @@ def test_copy_asset_file(tempdir): assert (subdir1 / 'asset.txt').read_text(encoding='utf8') == '# template data' # copy template file without context - src = (tempdir / 'asset.txt_t') + src = (tempdir / 'asset.txt.jinja') subdir2 = (tempdir / 'subdir2') subdir2.makedirs() 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(tempdir): @@ -65,12 +65,12 @@ def test_copy_asset(tempdir): source = (tempdir / 'source') source.makedirs() (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').makedirs() (source / '_static' / 'basic.css').write_text('basic.css', encoding='utf8') (source / '_templates').makedirs() (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 (tempdir / 'test1').exists() @@ -101,3 +101,14 @@ def excluded(path): assert not (destdir / '_static' / 'basic.css').exists() assert (destdir / '_templates' / 'layout.html').exists() assert not (destdir / '_templates' / 'sidebar.html').exists() + + +def test_template_basename(): + assert not _template_basename("asset.txt") + assert _template_basename("asset.txt.jinja") == "asset.txt" + assert _template_basename("sidebar.html.jinja") == "sidebar.html" + + +def test_legacy_template_basename(): + # TODO: deprecate '_t' template suffix support after 2024-12-31 + assert _template_basename("asset.txt_t") == "asset.txt" diff --git a/utils/babel_runner.py b/utils/babel_runner.py index 5e62efe86ca..3f963c9188a 100644 --- a/utils/babel_runner.py +++ b/utils/babel_runner.py @@ -42,7 +42,9 @@ # Extraction from Python source files ('**.py', extract_python), # Extraction from Jinja2 template files + ('**/templates/latex/**.tex.jinja', extract_jinja2), ('**/templates/latex/**.tex_t', extract_jinja2), + ('**/templates/latex/**.sty.jinja', extract_jinja2), ('**/templates/latex/**.sty_t', extract_jinja2), # Extraction from Jinja2 HTML templates ('**/themes/**.html', extract_jinja2), @@ -50,6 +52,7 @@ ('**/themes/**.xml', extract_jinja2), # Extraction from JavaScript files ('**.js', extract_javascript), + ('**.js.jinja', extract_javascript), ('**.js_t', extract_javascript), ] OPTIONS_MAP = { @@ -58,7 +61,9 @@ 'encoding': 'utf-8', }, # Extraction from Jinja2 template files + '**/templates/latex/**.tex.jinja': TEX_DELIMITERS.copy(), '**/templates/latex/**.tex_t': TEX_DELIMITERS.copy(), + '**/templates/latex/**.sty.jinja': TEX_DELIMITERS.copy(), '**/templates/latex/**.sty_t': TEX_DELIMITERS.copy(), # Extraction from Jinja2 HTML templates '**/themes/**.html': {