diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 75846100161..a314fcb07ef 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -127,7 +127,7 @@ def is_template_string(maybe_template: str) -> bool: class ResultWrapper: """Result wrapper class to store render result.""" - render_result: str + render_result: Optional[str] def gen_result_wrapper(kls): @@ -136,8 +136,8 @@ def gen_result_wrapper(kls): class Wrapper(kls, ResultWrapper): """Wrapper of a kls that can store render_result.""" - def __init__(self, value: kls, render_result: str) -> None: - super().__init__(value) + def __init__(self, *args: tuple, render_result: Optional[str] = None) -> None: + super().__init__(*args) self.render_result = render_result return Wrapper @@ -148,13 +148,15 @@ class TupleWrapper(tuple, ResultWrapper): # This is all magic to be allowed to subclass a tuple. - def __new__(cls, value: tuple, render_result: str) -> "TupleWrapper": + def __new__( + cls, value: tuple, *, render_result: Optional[str] = None + ) -> "TupleWrapper": """Create a new tuple class.""" return super().__new__(cls, tuple(value)) # pylint: disable=super-init-not-called - def __init__(self, value: tuple, render_result: str): + def __init__(self, value: tuple, *, render_result: Optional[str] = None): """Initialize a new tuple class.""" self.render_result = render_result @@ -416,7 +418,9 @@ class Template: result = literal_eval(render_result) if type(result) in RESULT_WRAPPERS: - result = RESULT_WRAPPERS[type(result)](result, render_result) + result = RESULT_WRAPPERS[type(result)]( + result, render_result=render_result + ) # If the literal_eval result is a string, use the original # render, by not returning right here. The evaluation of strings diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 750978b84ee..856fc1495e5 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -5,6 +5,7 @@ import random import pytest import pytz +import voluptuous as vol from homeassistant.components import group from homeassistant.config import async_process_ha_core_config @@ -2684,14 +2685,16 @@ async def test_is_static_still_ast_evals(hass): async def test_result_wrappers(hass): """Test result wrappers.""" - for text, native in ( - ("[1, 2]", [1, 2]), - ("{1, 2}", {1, 2}), - ("(1, 2)", (1, 2)), - ('{"hello": True}', {"hello": True}), + for text, native, orig_type, schema in ( + ("[1, 2]", [1, 2], list, vol.Schema([int])), + ("{1, 2}", {1, 2}, set, vol.Schema({int})), + ("(1, 2)", (1, 2), tuple, vol.ExactSequence([int, int])), + ('{"hello": True}', {"hello": True}, dict, vol.Schema({"hello": bool})), ): tpl = template.Template(text, hass) result = tpl.async_render() + assert isinstance(result, orig_type) assert isinstance(result, template.ResultWrapper) assert result == native assert result.render_result == text + schema(result) # should not raise