From b414a3cb389715da3460f9b0c540b11f45829c0e Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Fri, 17 May 2024 08:35:24 +0000 Subject: [PATCH] add strict mode to Jinja renders --- src/ibek/gen_scripts.py | 10 ++++++++-- src/ibek/utils.py | 4 ++-- tests/test_unit.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/ibek/gen_scripts.py b/src/ibek/gen_scripts.py index 91dd69fb7..cffa98241 100644 --- a/src/ibek/gen_scripts.py +++ b/src/ibek/gen_scripts.py @@ -5,7 +5,7 @@ import logging from typing import List, Sequence, Tuple -from jinja2 import Template +from jinja2 import StrictUndefined, Template from ibek.utils import UTILS @@ -31,7 +31,13 @@ def create_db_script( templates = renderer.render_database(extra_databases) - return Template(jinja_txt).render(templates=templates) + try: + return Template(jinja_txt).render( + templates=templates, undefined=StrictUndefined + ) + except Exception: + print(f"ERROR RENDERING DATABASE TEMPLATE:\n{templates}") + raise def create_boot_script(entities: Sequence[Entity]) -> str: diff --git a/src/ibek/utils.py b/src/ibek/utils.py index 8361287cd..dff8817dd 100644 --- a/src/ibek/utils.py +++ b/src/ibek/utils.py @@ -12,7 +12,7 @@ from pathlib import Path from typing import Any, Dict, Mapping -from jinja2 import Template +from jinja2 import StrictUndefined, Template @dataclass @@ -110,7 +110,7 @@ def render(self, context: Any, template_text: Any) -> str: return template_text try: - jinja_template = Template(template_text) + jinja_template = Template(template_text, undefined=StrictUndefined) return jinja_template.render( context, __utils__=self, diff --git a/tests/test_unit.py b/tests/test_unit.py index 2bbc5cc01..a5f978033 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -2,11 +2,17 @@ Some unit tests for ibek. """ +import dataclasses + +import jinja2 +import pytest + from ibek.args import IdArg, ObjectArg from ibek.commands import semver_compare from ibek.ioc import id_to_entity from ibek.ioc_factory import IocFactory from ibek.support import EntityDefinition, Support +from ibek.utils import UTILS def test_object_references(entity_factory): @@ -58,3 +64,28 @@ def test_compare(): assert semver_compare("1.1.1", "==1.1.1") assert semver_compare("1.1.1", ">=1.1.0") assert not semver_compare("1.1.1", ">=1.1.2") + + +@dataclasses.dataclass +class Person: + name: str + age: int + + +def test_strict(): + """ + validate that bad references in Jinja are caught + """ + p = Person("giles", 59) + + my_template = "{{ person.name ~ ' of age ' ~ person.age }}" + text = UTILS.render({"person": p}, my_template) + assert text == "giles of age 59" + + my_template = "{{ person.name ~ ' of age ' ~ height }}" + with pytest.raises(jinja2.exceptions.UndefinedError): + text = UTILS.render({"person": p}, my_template) + + my_template = "{{ person.name ~ ' of age ' ~ person.height }}" + with pytest.raises(jinja2.exceptions.UndefinedError): + text = UTILS.render({"person": p}, my_template)