Skip to content

Commit e8f5776

Browse files
committed
Register template filters on the fallback Jinja2 environment
When server.templates.path is configured, render_j2_template() creates a custom Environment and registers the to_json filter on it. If a requested template is not present in that directory, a second Environment is built for the built-in templates, but no filters were registered on it, so any built-in template using {{ ... | to_json }} (items.html, item.html, stac_items.html) failed with TemplateAssertionError: No filter named 'to_json'. Register the filter and global on the fallback environment as well, so a partial custom templates directory transparently falls back to the built-in templates. Adds tests/unittests/test_ogc_api_util.py covering both the custom template override and the fallback path.
1 parent 8b4396e commit e8f5776

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

pycsw/ogc/api/util.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ def render_j2_template(config, template, data):
219219
LOGGER.debug(err)
220220
LOGGER.debug('Custom template not found; using default')
221221
env = Environment(loader=FileSystemLoader(TEMPLATES))
222+
env.filters['to_json'] = to_json
223+
env.globals.update(to_json=to_json)
222224
template = env.get_template(template)
223225
else:
224226
raise
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# =================================================================
2+
#
3+
# Authors: Tom Kralidis
4+
#
5+
# Copyright (c) 2026 Tom Kralidis
6+
#
7+
# Permission is hereby granted, free of charge, to any person
8+
# obtaining a copy of this software and associated documentation
9+
# files (the "Software"), to deal in the Software without
10+
# restriction, including without limitation the rights to use,
11+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
# copies of the Software, and to permit persons to whom the
13+
# Software is furnished to do so, subject to the following
14+
# conditions:
15+
#
16+
# The above copyright notice and this permission notice shall be
17+
# included in all copies or substantial portions of the Software.
18+
#
19+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26+
# OTHER DEALINGS IN THE SOFTWARE.
27+
#
28+
# =================================================================
29+
"""Unit tests for pycsw.ogc.api.util"""
30+
31+
import pytest
32+
33+
from pycsw.ogc.api import util
34+
35+
pytestmark = pytest.mark.unit
36+
37+
TEMPLATE_USING_TO_JSON = "{{ data | to_json }}"
38+
39+
40+
def test_render_j2_template_custom_templates_path(tmp_path, monkeypatch):
41+
default_templates = tmp_path / 'default'
42+
default_templates.mkdir()
43+
(default_templates / 'items.html').write_text(TEMPLATE_USING_TO_JSON)
44+
monkeypatch.setattr(util, 'TEMPLATES', str(default_templates))
45+
46+
custom_templates = tmp_path / 'custom'
47+
custom_templates.mkdir()
48+
(custom_templates / 'items.html').write_text('custom')
49+
50+
config = {'server': {'templates': {'path': str(custom_templates)}}}
51+
52+
assert util.render_j2_template(config, 'items.html', {}) == 'custom'
53+
54+
55+
def test_render_j2_template_fallback_keeps_filters(tmp_path, monkeypatch):
56+
"""a template missing from templates.path falls back to the default
57+
templates, which must keep the to_json filter registered"""
58+
59+
default_templates = tmp_path / 'default'
60+
default_templates.mkdir()
61+
(default_templates / 'items.html').write_text(TEMPLATE_USING_TO_JSON)
62+
monkeypatch.setattr(util, 'TEMPLATES', str(default_templates))
63+
64+
custom_templates = tmp_path / 'custom'
65+
custom_templates.mkdir()
66+
(custom_templates / 'item.html').write_text('custom')
67+
68+
config = {'server': {'templates': {'path': str(custom_templates)}}}
69+
70+
assert util.render_j2_template(config, 'items.html', {}) == '{}'

0 commit comments

Comments
 (0)