Add apply to make macros/callables useful in filters and tests (#144227)

This commit is contained in:
David Poll 2025-05-26 08:00:07 -07:00 committed by GitHub
parent ca50fca738
commit 13d7234f97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 63 additions and 0 deletions

View File

@ -2019,6 +2019,11 @@ def add(value, amount, default=_SENTINEL):
return default
def apply(value, fn, *args, **kwargs):
"""Call the given callable with the provided arguments and keyword arguments."""
return fn(value, *args, **kwargs)
def logarithm(value, base=math.e, default=_SENTINEL):
"""Filter and function to get logarithm of the value with a specific base."""
try:
@ -3117,6 +3122,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
self.filters["acos"] = arc_cosine
self.filters["add"] = add
self.filters["apply"] = apply
self.filters["as_datetime"] = as_datetime
self.filters["as_local"] = dt_util.as_local
self.filters["as_timedelta"] = as_timedelta
@ -3177,6 +3183,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
self.filters["unpack"] = struct_unpack
self.filters["version"] = version
self.tests["apply"] = apply
self.tests["contains"] = contains
self.tests["datetime"] = _is_datetime
self.tests["is_number"] = is_number

View File

@ -772,6 +772,62 @@ def test_add(hass: HomeAssistant) -> None:
assert render(hass, "{{ 'no_number' | add(10, default=1) }}") == 1
def test_apply(hass: HomeAssistant) -> None:
"""Test apply."""
assert template.Template(
"""
{%- macro add_foo(arg) -%}
{{arg}}foo
{%- endmacro -%}
{{ ["a", "b", "c"] | map('apply', add_foo) | list }}
""",
hass,
).async_render() == ["afoo", "bfoo", "cfoo"]
assert template.Template(
"""
{{ ['1', '2', '3', '4', '5'] | map('apply', int) | list }}
""",
hass,
).async_render() == [1, 2, 3, 4, 5]
def test_apply_macro_with_arguments(hass: HomeAssistant) -> None:
"""Test apply macro with positional, named, and mixed arguments."""
# Test macro with positional arguments
assert template.Template(
"""
{%- macro greet(name, greeting) -%}
{{ greeting }}, {{ name }}!
{%- endmacro %}
{{ ["Alice", "Bob"] | map('apply', greet, "Hello") | list }}
""",
hass,
).async_render() == ["Hello, Alice!", "Hello, Bob!"]
# Test macro with named arguments
assert template.Template(
"""
{%- macro greet(name, greeting="Hi") -%}
{{ greeting }}, {{ name }}!
{%- endmacro %}
{{ ["Alice", "Bob"] | map('apply', greet, greeting="Hello") | list }}
""",
hass,
).async_render() == ["Hello, Alice!", "Hello, Bob!"]
# Test macro with mixed positional and named arguments
assert template.Template(
"""
{%- macro greet(name, separator, greeting="Hi") -%}
{{ greeting }}{{separator}} {{ name }}!
{%- endmacro %}
{{ ["Alice", "Bob"] | map('apply', greet, "," , greeting="Hey") | list }}
""",
hass,
).async_render() == ["Hey, Alice!", "Hey, Bob!"]
def test_logarithm(hass: HomeAssistant) -> None:
"""Test logarithm."""
tests = [