Extract version template function into a version Jinja2 extension (#167172)

Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
Franck Nijhof
2026-04-08 12:10:22 +02:00
committed by GitHub
parent 6cf5bbe2f5
commit b697b3a54e
5 changed files with 66 additions and 27 deletions

View File

@@ -18,7 +18,6 @@ from types import CodeType
from typing import TYPE_CHECKING, Any, Concatenate, Literal, NoReturn, Self, overload
import weakref
from awesomeversion import AwesomeVersion
import jinja2
from jinja2 import pass_context, pass_eval_context
from jinja2.runtime import AsyncLoopContext, LoopContext
@@ -1456,11 +1455,6 @@ def add(value, amount, default=_SENTINEL):
return default
def version(value):
"""Filter and function to get version object of the value."""
return AwesomeVersion(value)
def make_logging_undefined(
strict: bool | None, log_fn: Callable[[int, str], None] | None
) -> type[jinja2.Undefined]:
@@ -1611,13 +1605,11 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
self.add_extension(
"homeassistant.helpers.template.extensions.TypeCastExtension"
)
self.globals["version"] = version
self.add_extension("homeassistant.helpers.template.extensions.VersionExtension")
self.filters["add"] = add
self.filters["multiply"] = multiply
self.filters["round"] = forgiving_round
self.filters["version"] = version
if hass is None:
return

View File

@@ -15,6 +15,7 @@ from .regex import RegexExtension
from .serialization import SerializationExtension
from .string import StringExtension
from .type_cast import TypeCastExtension
from .version import VersionExtension
__all__ = [
"AreaExtension",
@@ -32,4 +33,5 @@ __all__ = [
"SerializationExtension",
"StringExtension",
"TypeCastExtension",
"VersionExtension",
]

View File

@@ -0,0 +1,35 @@
"""Version functions for Home Assistant templates."""
from __future__ import annotations
from typing import TYPE_CHECKING
from awesomeversion import AwesomeVersion
from .base import BaseTemplateExtension, TemplateFunction
if TYPE_CHECKING:
from homeassistant.helpers.template import TemplateEnvironment
class VersionExtension(BaseTemplateExtension):
"""Jinja2 extension for version functions."""
def __init__(self, environment: TemplateEnvironment) -> None:
"""Initialize the version extension."""
super().__init__(
environment,
functions=[
TemplateFunction(
"version",
self.version,
as_global=True,
as_filter=True,
),
],
)
@staticmethod
def version(value: str) -> AwesomeVersion:
"""Filter and function to get version object of the value."""
return AwesomeVersion(value)

View File

@@ -0,0 +1,28 @@
"""Test version functions for Home Assistant templates."""
from __future__ import annotations
import pytest
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import TemplateError
from tests.helpers.template.helpers import render
def test_version(hass: HomeAssistant) -> None:
"""Test version filter and function."""
filter_result = render(hass, "{{ '2099.9.9' | version}}")
function_result = render(hass, "{{ version('2099.9.9')}}")
assert filter_result == function_result == "2099.9.9"
filter_result = render(hass, "{{ '2099.9.9' | version < '2099.9.10' }}")
function_result = render(hass, "{{ version('2099.9.9') < '2099.9.10' }}")
assert filter_result is function_result is True
filter_result = render(hass, "{{ '2099.9.9' | version == '2099.9.9' }}")
function_result = render(hass, "{{ version('2099.9.9') == '2099.9.9' }}")
assert filter_result is function_result is True
with pytest.raises(TemplateError):
render(hass, "{{ version(None) < '2099.9.10' }}")

View File

@@ -954,24 +954,6 @@ def test_timedelta(mock_is_safe, hass: HomeAssistant) -> None:
assert result == "15 days"
def test_version(hass: HomeAssistant) -> None:
"""Test version filter and function."""
filter_result = render(hass, "{{ '2099.9.9' | version}}")
function_result = render(hass, "{{ version('2099.9.9')}}")
assert filter_result == function_result == "2099.9.9"
filter_result = render(hass, "{{ '2099.9.9' | version < '2099.9.10' }}")
function_result = render(hass, "{{ version('2099.9.9') < '2099.9.10' }}")
assert filter_result is function_result is True
filter_result = render(hass, "{{ '2099.9.9' | version == '2099.9.9' }}")
function_result = render(hass, "{{ version('2099.9.9') == '2099.9.9' }}")
assert filter_result is function_result is True
with pytest.raises(TemplateError):
render(hass, "{{ version(None) < '2099.9.10' }}")
def test_distance_function_with_1_state(hass: HomeAssistant) -> None:
"""Test distance function with 1 state."""
_set_up_units(hass)