Skip to content

Commit 78f26ed

Browse files
authored
Extend base jinja2 extension with limited template errors (home-assistant#156431)
1 parent 5e6a72d commit 78f26ed

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

homeassistant/helpers/template/extensions/base.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
from collections.abc import Callable
66
from dataclasses import dataclass
7-
from typing import TYPE_CHECKING, Any
7+
from typing import TYPE_CHECKING, Any, NoReturn
88

99
from jinja2.ext import Extension
1010
from jinja2.nodes import Node
1111
from jinja2.parser import Parser
1212

13+
from homeassistant.exceptions import TemplateError
14+
1315
if TYPE_CHECKING:
1416
from homeassistant.core import HomeAssistant
1517
from homeassistant.helpers.template import TemplateEnvironment
@@ -50,8 +52,17 @@ def __init__(
5052
if template_func.requires_hass and self.environment.hass is None:
5153
continue
5254

53-
# Skip functions not allowed in limited environments
55+
# Register unsupported stub for functions not allowed in limited environments
5456
if self.environment.limited and not template_func.limited_ok:
57+
unsupported_func = self._create_unsupported_function(
58+
template_func.name
59+
)
60+
if template_func.as_global:
61+
environment.globals[template_func.name] = unsupported_func
62+
if template_func.as_filter:
63+
environment.filters[template_func.name] = unsupported_func
64+
if template_func.as_test:
65+
environment.tests[template_func.name] = unsupported_func
5566
continue
5667

5768
if template_func.as_global:
@@ -61,6 +72,17 @@ def __init__(
6172
if template_func.as_test:
6273
environment.tests[template_func.name] = template_func.func
6374

75+
@staticmethod
76+
def _create_unsupported_function(name: str) -> Callable[[], NoReturn]:
77+
"""Create a function that raises an error for unsupported functions in limited templates."""
78+
79+
def unsupported(*args: Any, **kwargs: Any) -> NoReturn:
80+
raise TemplateError(
81+
f"Use of '{name}' is not supported in limited templates"
82+
)
83+
84+
return unsupported
85+
6486
@property
6587
def hass(self) -> HomeAssistant:
6688
"""Return the Home Assistant instance.

tests/helpers/template/extensions/test_base.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66

7+
from homeassistant.exceptions import TemplateError
78
from homeassistant.helpers.template import TemplateEnvironment
89
from homeassistant.helpers.template.extensions.base import (
910
BaseTemplateExtension,
@@ -86,7 +87,7 @@ def test_func() -> str:
8687

8788

8889
def test_limited_ok_functions_not_registered_in_limited_env() -> None:
89-
"""Test that functions with limited_ok=False are not registered in limited env."""
90+
"""Test that functions with limited_ok=False raise error in limited env."""
9091
# Create a limited environment without hass
9192
env = TemplateEnvironment(None, limited=True)
9293

@@ -116,9 +117,18 @@ def restricted_func() -> str:
116117
],
117118
)
118119

119-
# Only the allowed function should be registered
120+
# The allowed function should be registered and work
120121
assert "allowed_func" in env.globals
121-
assert "restricted_func" not in env.globals
122+
assert env.globals["allowed_func"]() == "allowed"
123+
124+
# The restricted function should be registered but raise TemplateError
125+
assert "restricted_func" in env.globals
126+
with pytest.raises(
127+
TemplateError,
128+
match="Use of 'restricted_func' is not supported in limited templates",
129+
):
130+
env.globals["restricted_func"]()
131+
122132
assert extension is not None
123133

124134

0 commit comments

Comments
 (0)