Make result wrappers more robust (#42488)
This commit is contained in:
parent
2effbb6604
commit
cb453d3ae1
2 changed files with 18 additions and 11 deletions
|
@ -127,7 +127,7 @@ def is_template_string(maybe_template: str) -> bool:
|
||||||
class ResultWrapper:
|
class ResultWrapper:
|
||||||
"""Result wrapper class to store render result."""
|
"""Result wrapper class to store render result."""
|
||||||
|
|
||||||
render_result: str
|
render_result: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
def gen_result_wrapper(kls):
|
def gen_result_wrapper(kls):
|
||||||
|
@ -136,8 +136,8 @@ def gen_result_wrapper(kls):
|
||||||
class Wrapper(kls, ResultWrapper):
|
class Wrapper(kls, ResultWrapper):
|
||||||
"""Wrapper of a kls that can store render_result."""
|
"""Wrapper of a kls that can store render_result."""
|
||||||
|
|
||||||
def __init__(self, value: kls, render_result: str) -> None:
|
def __init__(self, *args: tuple, render_result: Optional[str] = None) -> None:
|
||||||
super().__init__(value)
|
super().__init__(*args)
|
||||||
self.render_result = render_result
|
self.render_result = render_result
|
||||||
|
|
||||||
return Wrapper
|
return Wrapper
|
||||||
|
@ -148,13 +148,15 @@ class TupleWrapper(tuple, ResultWrapper):
|
||||||
|
|
||||||
# This is all magic to be allowed to subclass a tuple.
|
# 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."""
|
"""Create a new tuple class."""
|
||||||
return super().__new__(cls, tuple(value))
|
return super().__new__(cls, tuple(value))
|
||||||
|
|
||||||
# pylint: disable=super-init-not-called
|
# 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."""
|
"""Initialize a new tuple class."""
|
||||||
self.render_result = render_result
|
self.render_result = render_result
|
||||||
|
|
||||||
|
@ -416,7 +418,9 @@ class Template:
|
||||||
result = literal_eval(render_result)
|
result = literal_eval(render_result)
|
||||||
|
|
||||||
if type(result) in RESULT_WRAPPERS:
|
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
|
# If the literal_eval result is a string, use the original
|
||||||
# render, by not returning right here. The evaluation of strings
|
# render, by not returning right here. The evaluation of strings
|
||||||
|
|
|
@ -5,6 +5,7 @@ import random
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import pytz
|
import pytz
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import group
|
from homeassistant.components import group
|
||||||
from homeassistant.config import async_process_ha_core_config
|
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):
|
async def test_result_wrappers(hass):
|
||||||
"""Test result wrappers."""
|
"""Test result wrappers."""
|
||||||
for text, native in (
|
for text, native, orig_type, schema in (
|
||||||
("[1, 2]", [1, 2]),
|
("[1, 2]", [1, 2], list, vol.Schema([int])),
|
||||||
("{1, 2}", {1, 2}),
|
("{1, 2}", {1, 2}, set, vol.Schema({int})),
|
||||||
("(1, 2)", (1, 2)),
|
("(1, 2)", (1, 2), tuple, vol.ExactSequence([int, int])),
|
||||||
('{"hello": True}', {"hello": True}),
|
('{"hello": True}', {"hello": True}, dict, vol.Schema({"hello": bool})),
|
||||||
):
|
):
|
||||||
tpl = template.Template(text, hass)
|
tpl = template.Template(text, hass)
|
||||||
result = tpl.async_render()
|
result = tpl.async_render()
|
||||||
|
assert isinstance(result, orig_type)
|
||||||
assert isinstance(result, template.ResultWrapper)
|
assert isinstance(result, template.ResultWrapper)
|
||||||
assert result == native
|
assert result == native
|
||||||
assert result.render_result == text
|
assert result.render_result == text
|
||||||
|
schema(result) # should not raise
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue