mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Allow template int filter to render from a bytes based integer (#60452)
* Allow template int to render bytes * re-triggering tests * Add warning when base !=10 and rendering bytes * re-trigger tests * Re-trigger tests * remove period * Update homeassistant/helpers/template.py Co-authored-by: Erik Montnemery <erik@montnemery.com> * Fix logger syntax * remove parentheses Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
2a2a20fcb3
commit
f07e676c82
@ -1567,8 +1567,15 @@ def forgiving_float_filter(value, default=_SENTINEL):
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def forgiving_int(value, default=_SENTINEL, base=10):
|
def forgiving_int(value, default=_SENTINEL, base=10, little_endian=False):
|
||||||
"""Try to convert value to an int, and warn if it fails."""
|
"""Try to convert value to an int, and warn if it fails."""
|
||||||
|
if isinstance(value, bytes) and value:
|
||||||
|
if base != 10:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Template warning: 'int' got 'bytes' type input, ignoring base=%s parameter",
|
||||||
|
base,
|
||||||
|
)
|
||||||
|
return convert_to_int(value, little_endian=little_endian)
|
||||||
result = jinja2.filters.do_int(value, default=default, base=base)
|
result = jinja2.filters.do_int(value, default=default, base=base)
|
||||||
if result is _SENTINEL:
|
if result is _SENTINEL:
|
||||||
warn_no_default("int", value, value)
|
warn_no_default("int", value, value)
|
||||||
@ -1576,8 +1583,15 @@ def forgiving_int(value, default=_SENTINEL, base=10):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def forgiving_int_filter(value, default=_SENTINEL, base=10):
|
def forgiving_int_filter(value, default=_SENTINEL, base=10, little_endian=False):
|
||||||
"""Try to convert value to an int, and warn if it fails."""
|
"""Try to convert value to an int, and warn if it fails."""
|
||||||
|
if isinstance(value, bytes) and value:
|
||||||
|
if base != 10:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Template warning: 'int' got 'bytes' type input, ignoring base=%s parameter",
|
||||||
|
base,
|
||||||
|
)
|
||||||
|
return convert_to_int(value, little_endian=little_endian)
|
||||||
result = jinja2.filters.do_int(value, default=default, base=base)
|
result = jinja2.filters.do_int(value, default=default, base=base)
|
||||||
if result is _SENTINEL:
|
if result is _SENTINEL:
|
||||||
warn_no_default("int", value, 0)
|
warn_no_default("int", value, 0)
|
||||||
|
@ -252,7 +252,7 @@ def test_float_filter(hass):
|
|||||||
assert render(hass, "{{ 'bad' | float(default=1) }}") == 1
|
assert render(hass, "{{ 'bad' | float(default=1) }}") == 1
|
||||||
|
|
||||||
|
|
||||||
def test_int_filter(hass):
|
def test_int_filter(hass, caplog):
|
||||||
"""Test int filter."""
|
"""Test int filter."""
|
||||||
hass.states.async_set("sensor.temperature", "12.2")
|
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 }}") == 12
|
||||||
@ -265,8 +265,25 @@ def test_int_filter(hass):
|
|||||||
assert render(hass, "{{ 'bad' | int(1) }}") == 1
|
assert render(hass, "{{ 'bad' | int(1) }}") == 1
|
||||||
assert render(hass, "{{ 'bad' | int(default=1) }}") == 1
|
assert render(hass, "{{ 'bad' | int(default=1) }}") == 1
|
||||||
|
|
||||||
|
# Test with bytes based integer
|
||||||
|
variables = {"value": b"\xde\xad\xbe\xef"}
|
||||||
|
assert (render(hass, "{{ value | int }}", variables=variables)) == 0xDEADBEEF
|
||||||
|
assert (
|
||||||
|
render(hass, "{{ value | int(little_endian=True) }}", variables=variables)
|
||||||
|
== 0xEFBEADDE
|
||||||
|
)
|
||||||
|
|
||||||
def test_int_function(hass):
|
# Test with base and base parameter set
|
||||||
|
assert (
|
||||||
|
render(hass, "{{ value | int(base=16) }}", variables=variables)
|
||||||
|
) == 0xDEADBEEF
|
||||||
|
assert (
|
||||||
|
"Template warning: 'int' got 'bytes' type input, ignoring base=16 parameter"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_int_function(hass, caplog):
|
||||||
"""Test int filter."""
|
"""Test int filter."""
|
||||||
hass.states.async_set("sensor.temperature", "12.2")
|
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) }}") == 12
|
||||||
@ -279,6 +296,22 @@ def test_int_function(hass):
|
|||||||
assert render(hass, "{{ int('bad', 1) }}") == 1
|
assert render(hass, "{{ int('bad', 1) }}") == 1
|
||||||
assert render(hass, "{{ int('bad', default=1) }}") == 1
|
assert render(hass, "{{ int('bad', default=1) }}") == 1
|
||||||
|
|
||||||
|
# Test with base and base parameter set
|
||||||
|
variables = {"value": b"\xde\xad\xbe\xef"}
|
||||||
|
assert (render(hass, "{{ int(value) }}", variables=variables)) == 0xDEADBEEF
|
||||||
|
assert (
|
||||||
|
render(hass, "{{ int(value, little_endian=True) }}", variables=variables)
|
||||||
|
== 0xEFBEADDE
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
render(hass, "{{ int(value, base=16) }}", variables=variables)
|
||||||
|
) == 0xDEADBEEF
|
||||||
|
assert (
|
||||||
|
"Template warning: 'int' got 'bytes' type input, ignoring base=16 parameter"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"value, expected",
|
"value, expected",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user