Override the jinja2 int filter (#57470)

pull/57510/head
Erik Montnemery 2021-10-12 00:12:42 +02:00 committed by GitHub
parent a36a765352
commit 7acb1b6eb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 1 deletions

View File

@ -1211,7 +1211,7 @@ def warn_no_default(function, value, default):
(
"Template warning: '%s' got invalid input '%s' when %s template '%s' "
"but no default was specified. Currently '%s' will return '%s', however this template will fail "
"to render in Home Assistant core 2021.12"
"to render in Home Assistant core 2022.1"
),
function,
value,
@ -1463,6 +1463,24 @@ def forgiving_float_filter(value, default=_SENTINEL):
return default
def forgiving_int(value, default=_SENTINEL, base=10):
"""Try to convert value to an int, and warn if it fails."""
result = jinja2.filters.do_int(value, default=default, base=base)
if result is _SENTINEL:
warn_no_default("int", value, value)
return value
return result
def forgiving_int_filter(value, default=_SENTINEL, base=10):
"""Try to convert value to an int, and warn if it fails."""
result = jinja2.filters.do_int(value, default=default, base=base)
if result is _SENTINEL:
warn_no_default("int", value, 0)
return 0
return result
def is_number(value):
"""Try to convert value to a float."""
try:
@ -1693,6 +1711,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
self.filters["ord"] = ord
self.filters["is_number"] = is_number
self.filters["float"] = forgiving_float_filter
self.filters["int"] = forgiving_int_filter
self.globals["log"] = logarithm
self.globals["sin"] = sine
self.globals["cos"] = cosine
@ -1716,6 +1735,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
self.globals["max"] = max
self.globals["min"] = min
self.globals["is_number"] = is_number
self.globals["int"] = forgiving_int
self.tests["match"] = regex_match
self.tests["search"] = regex_search

View File

@ -240,6 +240,34 @@ def test_float_filter(hass):
assert render(hass, "{{ 'bad' | float(default=1) }}") == 1
def test_int_filter(hass):
"""Test int filter."""
hass.states.async_set("sensor.temperature", "12.2")
assert render(hass, "{{ states.sensor.temperature.state | int }}") == 12
assert render(hass, "{{ states.sensor.temperature.state | int > 11 }}") is True
hass.states.async_set("sensor.temperature", "0x10")
assert render(hass, "{{ states.sensor.temperature.state | int(base=16) }}") == 16
assert render(hass, "{{ 'bad' | int }}") == 0
assert render(hass, "{{ 'bad' | int(1) }}") == 1
assert render(hass, "{{ 'bad' | int(default=1) }}") == 1
def test_int_function(hass):
"""Test int filter."""
hass.states.async_set("sensor.temperature", "12.2")
assert render(hass, "{{ int(states.sensor.temperature.state) }}") == 12
assert render(hass, "{{ int(states.sensor.temperature.state) > 11 }}") is True
hass.states.async_set("sensor.temperature", "0x10")
assert render(hass, "{{ int(states.sensor.temperature.state, base=16) }}") == 16
assert render(hass, "{{ int('bad') }}") == "bad"
assert render(hass, "{{ int('bad', 1) }}") == 1
assert render(hass, "{{ int('bad', default=1) }}") == 1
@pytest.mark.parametrize(
"value, expected",
[