diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index dafa77da972..77d0819e10d 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -2,9 +2,11 @@ from datetime import datetime import json import logging +import random import re import jinja2 +from jinja2 import contextfilter from jinja2.sandbox import ImmutableSandboxedEnvironment from homeassistant.const import ( @@ -418,6 +420,16 @@ def forgiving_float(value): return value +@contextfilter +def random_every_time(context, values): + """Choose a random value. + + Unlike Jinja's random filter, + this is context-dependent to avoid caching the chosen value. + """ + return random.choice(values) + + class TemplateEnvironment(ImmutableSandboxedEnvironment): """The Home Assistant template environment.""" @@ -435,6 +447,7 @@ ENV.filters['timestamp_utc'] = timestamp_utc ENV.filters['is_defined'] = fail_when_undefined ENV.filters['max'] = max ENV.filters['min'] = min +ENV.filters['random'] = random_every_time ENV.globals['float'] = forgiving_float ENV.globals['now'] = dt_util.now ENV.globals['utcnow'] = dt_util.utcnow diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 71075124f32..117ab971f9d 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -1,6 +1,7 @@ """Test Home Assistant template helper methods.""" from datetime import datetime import unittest +import random from unittest.mock import patch from homeassistant.components import group @@ -232,6 +233,15 @@ class TestHelpersTemplate(unittest.TestCase): self.assertEqual("1706951424.0", template.Template(tpl, self.hass).render()) + @patch.object(random, 'choice') + def test_random_every_time(self, test_choice): + """Ensure the random filter runs every time, not just once.""" + tpl = template.Template('{{ [1,2] | random }}', self.hass) + test_choice.return_value = 'foo' + self.assertEqual('foo', tpl.render()) + test_choice.return_value = 'bar' + self.assertEqual('bar', tpl.render()) + def test_passing_vars_as_keywords(self): """Test passing variables as keywords.""" self.assertEqual(