Warn if template functions fail and no default is specified (#56453)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
Erik Montnemery 2021-09-29 20:16:02 +02:00 committed by GitHub
parent ae00c221e0
commit ef13e473cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 280 additions and 64 deletions

View file

@ -38,6 +38,12 @@ def _set_up_units(hass):
)
def render(hass, template_str, variables=None):
"""Create render info from template."""
tmp = template.Template(template_str, hass)
return tmp.async_render(variables)
def render_to_info(hass, template_str, variables=None):
"""Create render info from template."""
tmp = template.Template(template_str, hass)
@ -196,8 +202,8 @@ def test_iterating_domain_states(hass):
)
def test_float(hass):
"""Test float."""
def test_float_function(hass):
"""Test float function."""
hass.states.async_set("sensor.temperature", "12")
assert (
@ -219,6 +225,20 @@ def test_float(hass):
== "forgiving"
)
assert render(hass, "{{ float('bad', 1) }}") == 1
assert render(hass, "{{ float('bad', default=1) }}") == 1
def test_float_filter(hass):
"""Test float filter."""
hass.states.async_set("sensor.temperature", "12")
assert render(hass, "{{ states.sensor.temperature.state | float }}") == 12.0
assert render(hass, "{{ states.sensor.temperature.state | float > 11 }}") is True
assert render(hass, "{{ 'bad' | float }}") == 0
assert render(hass, "{{ 'bad' | float(1) }}") == 1
assert render(hass, "{{ 'bad' | float(default=1) }}") == 1
@pytest.mark.parametrize(
"value, expected",
@ -295,8 +315,8 @@ def test_rounding_value(hass):
)
def test_rounding_value_get_original_value_on_error(hass):
"""Test rounding value get original value on error."""
def test_rounding_value_on_error(hass):
"""Test rounding value handling of error."""
assert template.Template("{{ None | round }}", hass).async_render() is None
assert (
@ -304,6 +324,9 @@ def test_rounding_value_get_original_value_on_error(hass):
== "no_number"
)
# Test handling of default return value
assert render(hass, "{{ 'no_number' | round(default=1) }}") == 1
def test_multiply(hass):
"""Test multiply."""
@ -317,6 +340,10 @@ def test_multiply(hass):
== out
)
# Test handling of default return value
assert render(hass, "{{ 'no_number' | multiply(10, 1) }}") == 1
assert render(hass, "{{ 'no_number' | multiply(10, default=1) }}") == 1
def test_logarithm(hass):
"""Test logarithm."""
@ -343,6 +370,12 @@ def test_logarithm(hass):
== expected
)
# Test handling of default return value
assert render(hass, "{{ 'no_number' | log(10, 1) }}") == 1
assert render(hass, "{{ 'no_number' | log(10, default=1) }}") == 1
assert render(hass, "{{ log('no_number', 10, 1) }}") == 1
assert render(hass, "{{ log('no_number', 10, default=1) }}") == 1
def test_sine(hass):
"""Test sine."""
@ -360,6 +393,13 @@ def test_sine(hass):
template.Template("{{ %s | sin | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ sin({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | sin(1) }}") == 1
assert render(hass, "{{ 'no_number' | sin(default=1) }}") == 1
assert render(hass, "{{ sin('no_number', 1) }}") == 1
assert render(hass, "{{ sin('no_number', default=1) }}") == 1
def test_cos(hass):
@ -378,6 +418,13 @@ def test_cos(hass):
template.Template("{{ %s | cos | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ cos({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | sin(1) }}") == 1
assert render(hass, "{{ 'no_number' | sin(default=1) }}") == 1
assert render(hass, "{{ sin('no_number', 1) }}") == 1
assert render(hass, "{{ sin('no_number', default=1) }}") == 1
def test_tan(hass):
@ -396,6 +443,13 @@ def test_tan(hass):
template.Template("{{ %s | tan | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ tan({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | tan(1) }}") == 1
assert render(hass, "{{ 'no_number' | tan(default=1) }}") == 1
assert render(hass, "{{ tan('no_number', 1) }}") == 1
assert render(hass, "{{ tan('no_number', default=1) }}") == 1
def test_sqrt(hass):
@ -414,6 +468,13 @@ def test_sqrt(hass):
template.Template("{{ %s | sqrt | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ sqrt({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | sqrt(1) }}") == 1
assert render(hass, "{{ 'no_number' | sqrt(default=1) }}") == 1
assert render(hass, "{{ sqrt('no_number', 1) }}") == 1
assert render(hass, "{{ sqrt('no_number', default=1) }}") == 1
def test_arc_sine(hass):
@ -434,6 +495,13 @@ def test_arc_sine(hass):
template.Template("{{ %s | asin | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ asin({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | asin(1) }}") == 1
assert render(hass, "{{ 'no_number' | asin(default=1) }}") == 1
assert render(hass, "{{ asin('no_number', 1) }}") == 1
assert render(hass, "{{ asin('no_number', default=1) }}") == 1
def test_arc_cos(hass):
@ -454,6 +522,13 @@ def test_arc_cos(hass):
template.Template("{{ %s | acos | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ acos({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | acos(1) }}") == 1
assert render(hass, "{{ 'no_number' | acos(default=1) }}") == 1
assert render(hass, "{{ acos('no_number', 1) }}") == 1
assert render(hass, "{{ acos('no_number', default=1) }}") == 1
def test_arc_tan(hass):
@ -476,6 +551,13 @@ def test_arc_tan(hass):
template.Template("{{ %s | atan | round(3) }}" % value, hass).async_render()
== expected
)
assert render(hass, f"{{{{ atan({value}) | round(3) }}}}") == expected
# Test handling of default return value
assert render(hass, "{{ 'no_number' | atan(1) }}") == 1
assert render(hass, "{{ 'no_number' | atan(default=1) }}") == 1
assert render(hass, "{{ atan('no_number', 1) }}") == 1
assert render(hass, "{{ atan('no_number', default=1) }}") == 1
def test_arc_tan2(hass):
@ -510,6 +592,12 @@ def test_arc_tan2(hass):
== expected
)
# Test handling of default return value
assert render(hass, "{{ ('duck', 'goose') | atan2(1) }}") == 1
assert render(hass, "{{ ('duck', 'goose') | atan2(default=1) }}") == 1
assert render(hass, "{{ atan2('duck', 'goose', 1) }}") == 1
assert render(hass, "{{ atan2('duck', 'goose', default=1) }}") == 1
def test_strptime(hass):
"""Test the parse timestamp method."""
@ -532,6 +620,10 @@ def test_strptime(hass):
assert template.Template(temp, hass).async_render() == expected
# Test handling of default return value
assert render(hass, "{{ strptime('invalid', '%Y', 1) }}") == 1
assert render(hass, "{{ strptime('invalid', '%Y', default=1) }}") == 1
def test_timestamp_custom(hass):
"""Test the timestamps to custom filter."""
@ -554,6 +646,10 @@ def test_timestamp_custom(hass):
assert template.Template(f"{{{{ {inp} | {fil} }}}}", hass).async_render() == out
# Test handling of default return value
assert render(hass, "{{ None | timestamp_custom('invalid', True, 1) }}") == 1
assert render(hass, "{{ None | timestamp_custom(default=1) }}") == 1
def test_timestamp_local(hass):
"""Test the timestamps to local filter."""
@ -565,6 +661,10 @@ def test_timestamp_local(hass):
== out
)
# Test handling of default return value
assert render(hass, "{{ None | timestamp_local(1) }}") == 1
assert render(hass, "{{ None | timestamp_local(default=1) }}") == 1
@pytest.mark.parametrize(
"input",
@ -702,6 +802,10 @@ def test_timestamp_utc(hass):
== out
)
# Test handling of default return value
assert render(hass, "{{ None | timestamp_utc(1) }}") == 1
assert render(hass, "{{ None | timestamp_utc(default=1) }}") == 1
def test_as_timestamp(hass):
"""Test the as_timestamp function."""
@ -720,6 +824,12 @@ def test_as_timestamp(hass):
)
assert template.Template(tpl, hass).async_render() == 1706951424.0
# Test handling of default return value
assert render(hass, "{{ 'invalid' | as_timestamp(1) }}") == 1
assert render(hass, "{{ 'invalid' | as_timestamp(default=1) }}") == 1
assert render(hass, "{{ as_timestamp('invalid', 1) }}") == 1
assert render(hass, "{{ as_timestamp('invalid', default=1) }}") == 1
@patch.object(random, "choice")
def test_random_every_time(test_choice, hass):