diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index b5e62ee2fcd..618bc6ea4f7 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -9,6 +9,7 @@ import math import random import re from typing import Any, Dict, Iterable, List, Optional, Union +from urllib.parse import urlencode as urllib_urlencode import jinja2 from jinja2 import contextfilter, contextfunction @@ -945,6 +946,11 @@ def relative_time(value): return dt_util.get_age(value) +def urlencode(value): + """Urlencode dictionary and return as UTF-8 string.""" + return urllib_urlencode(value).encode("utf-8") + + class TemplateEnvironment(ImmutableSandboxedEnvironment): """The Home Assistant template environment.""" @@ -1001,6 +1007,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): self.globals["as_timestamp"] = forgiving_as_timestamp self.globals["relative_time"] = relative_time self.globals["strptime"] = strptime + self.globals["urlencode"] = urlencode if hass is None: return diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 3f3eb7a800c..f755e4e1084 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -1872,3 +1872,16 @@ def test_render_complex_handling_non_template_values(hass): assert template.render_complex( {True: 1, False: template.Template("{{ hello }}", hass)}, {"hello": 2} ) == {True: 1, False: "2"} + + +def test_urlencode(hass): + """Test the urlencode method.""" + tpl = template.Template( + ("{% set dict = {'foo': 'x&y', 'bar': 42} %}" "{{ dict | urlencode }}"), hass, + ) + assert tpl.async_render() == "foo=x%26y&bar=42" + tpl = template.Template( + ("{% set string = 'the quick brown fox = true' %}" "{{ string | urlencode }}"), + hass, + ) + assert tpl.async_render() == "the%20quick%20brown%20fox%20%3D%20true"