diff --git a/app/templates.py b/app/templates.py new file mode 100644 index 0000000..d18f103 --- /dev/null +++ b/app/templates.py @@ -0,0 +1,43 @@ +import re +from typing import Any, Dict + +import jinja2 + +# Create a minimal Jinja2 environment for text templates. +# Use StrictUndefined so missing variables raise exceptions during rendering. +ENV = jinja2.Environment( + undefined=jinja2.StrictUndefined, + autoescape=False, +) + + +def _convert_braced_format_to_jinja(template: str) -> str: + """ + Convert simple `{var}` style placeholders into Jinja `{{ var }}` so legacy templates keep working. + This will not touch existing `{{ }}` or `{% %}`. + """ + # Skip conversion if template already contains jinja markers + if ("{{" in template) or ("{%" in template): + return template + + # Replace single-brace simple identifiers like {a_b} or {a.b} -> {{ a_b }} or {{ a.b }} + pattern = re.compile(r'(? str: + """ + Safely render a template string using Jinja2 with StrictUndefined. + - Accepts legacy `{var}` placeholders by converting them to Jinja style. + - Raises jinja2 exceptions when rendering fails. + """ + if template_str is None: + raise ValueError("template_str is None") + + tpl = _convert_braced_format_to_jinja(template_str) + jtpl = ENV.from_string(tpl) + # Jinja expects normal Python types in context; if context contains Pydantic models, + # they should be converted by caller to plain dicts. + return jtpl.render(**context) + + diff --git a/tests/test_templates.py b/tests/test_templates.py new file mode 100644 index 0000000..fd0a042 --- /dev/null +++ b/tests/test_templates.py @@ -0,0 +1,19 @@ +import pytest + +from app.templates import safe_render + + +def test_safe_render_legacy_and_nested(): + tpl = "收到{actual_ref_amt}元 by {trans_order_info.remark}" + ctx = {"actual_ref_amt": 88.88, "trans_order_info": {"remark": "order123"}} + out = safe_render(tpl, ctx) + assert "88.88" in out + assert "order123" in out + + +def test_safe_render_missing_var_raises(): + tpl = "Hello {missing_var}" + with pytest.raises(Exception): + safe_render(tpl, {}) + +