mirror of
https://github.com/home-assistant/core.git
synced 2025-04-19 14:57:52 +00:00
Add template function: combine (#140948)
* Add template function: combine * Add test to take away concern raised
This commit is contained in:
parent
3fb0290fba
commit
c6d3928ed1
@ -2785,6 +2785,32 @@ def flatten(value: Iterable[Any], levels: int | None = None) -> list[Any]:
|
||||
return flattened
|
||||
|
||||
|
||||
def combine(*args: Any, recursive: bool = False) -> dict[Any, Any]:
|
||||
"""Combine multiple dictionaries into one."""
|
||||
if not args:
|
||||
raise TypeError("combine expected at least 1 argument, got 0")
|
||||
|
||||
result: dict[Any, Any] = {}
|
||||
for arg in args:
|
||||
if not isinstance(arg, dict):
|
||||
raise TypeError(f"combine expected a dict, got {type(arg).__name__}")
|
||||
|
||||
if recursive:
|
||||
for key, value in arg.items():
|
||||
if (
|
||||
key in result
|
||||
and isinstance(result[key], dict)
|
||||
and isinstance(value, dict)
|
||||
):
|
||||
result[key] = combine(result[key], value, recursive=True)
|
||||
else:
|
||||
result[key] = value
|
||||
else:
|
||||
result |= arg
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def md5(value: str) -> str:
|
||||
"""Generate md5 hash from a string."""
|
||||
return hashlib.md5(value.encode()).hexdigest()
|
||||
@ -3012,6 +3038,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
|
||||
self.filters["sha1"] = sha1
|
||||
self.filters["sha256"] = sha256
|
||||
self.filters["sha512"] = sha512
|
||||
self.filters["combine"] = combine
|
||||
self.globals["log"] = logarithm
|
||||
self.globals["sin"] = sine
|
||||
self.globals["cos"] = cosine
|
||||
@ -3056,6 +3083,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
|
||||
self.globals["sha1"] = sha1
|
||||
self.globals["sha256"] = sha256
|
||||
self.globals["sha512"] = sha512
|
||||
self.globals["combine"] = combine
|
||||
self.tests["is_number"] = is_number
|
||||
self.tests["list"] = _is_list
|
||||
self.tests["set"] = _is_set
|
||||
|
@ -6840,3 +6840,39 @@ def test_sha512(hass: HomeAssistant) -> None:
|
||||
template.Template("{{ 'Home Assistant' | sha512 }}", hass).async_render()
|
||||
== "9e3c2cdd1fbab0037378d37e1baf8a3a4bf92c54b56ad1d459deee30ccbb2acbebd7a3614552ea08992ad27dedeb7b4c5473525ba90cb73dbe8b9ec5f69295bb"
|
||||
)
|
||||
|
||||
|
||||
def test_combine(hass: HomeAssistant) -> None:
|
||||
"""Test combine filter and function."""
|
||||
assert template.Template(
|
||||
"{{ {'a': 1, 'b': 2} | combine({'b': 3, 'c': 4}) }}", hass
|
||||
).async_render() == {"a": 1, "b": 3, "c": 4}
|
||||
|
||||
assert template.Template(
|
||||
"{{ combine({'a': 1, 'b': 2}, {'b': 3, 'c': 4}) }}", hass
|
||||
).async_render() == {"a": 1, "b": 3, "c": 4}
|
||||
|
||||
assert template.Template(
|
||||
"{{ combine({'a': 1, 'b': {'x': 1}}, {'b': {'y': 2}, 'c': 4}, recursive=True) }}",
|
||||
hass,
|
||||
).async_render() == {"a": 1, "b": {"x": 1, "y": 2}, "c": 4}
|
||||
|
||||
# Test that recursive=False does not merge nested dictionaries
|
||||
assert template.Template(
|
||||
"{{ combine({'a': 1, 'b': {'x': 1}}, {'b': {'y': 2}, 'c': 4}, recursive=False) }}",
|
||||
hass,
|
||||
).async_render() == {"a": 1, "b": {"y": 2}, "c": 4}
|
||||
|
||||
# Test that None values are handled correctly in recursive merge
|
||||
assert template.Template(
|
||||
"{{ combine({'a': 1, 'b': none}, {'b': {'y': 2}, 'c': 4}, recursive=True) }}",
|
||||
hass,
|
||||
).async_render() == {"a": 1, "b": {"y": 2}, "c": 4}
|
||||
|
||||
with pytest.raises(
|
||||
TemplateError, match="combine expected at least 1 argument, got 0"
|
||||
):
|
||||
template.Template("{{ combine() }}", hass).async_render()
|
||||
|
||||
with pytest.raises(TemplateError, match="combine expected a dict, got str"):
|
||||
template.Template("{{ {'a': 1} | combine('not a dict') }}", hass).async_render()
|
||||
|
Loading…
x
Reference in New Issue
Block a user