Add support for logarithm in templates (#10824)

* Add support for logarithm in templates

This adds a 'log' filter that takes the logarithm of the given value,
with an optional base number. The base defaults to 'e' - the natural
logarithm

* Remove usage of log10 in template filter 'log'

* Add logarithm as a global

This makes it possible to write:
'{{ log(4, 2) }}'
This commit is contained in:
Odin Ugedal 2017-11-28 06:29:01 +01:00 committed by Paulus Schoutsen
parent 27270b49b4
commit 0668fba7bd
2 changed files with 35 additions and 0 deletions

View File

@ -4,6 +4,7 @@ import json
import logging import logging
import random import random
import re import re
import math
import jinja2 import jinja2
from jinja2 import contextfilter from jinja2 import contextfilter
@ -423,6 +424,14 @@ def multiply(value, amount):
return value return value
def logarithm(value, base=math.e):
"""Filter to get logarithm of the value with a spesific base."""
try:
return math.log(float(value), float(base))
except (ValueError, TypeError):
return value
def timestamp_custom(value, date_format=DATE_STR_FORMAT, local=True): def timestamp_custom(value, date_format=DATE_STR_FORMAT, local=True):
"""Filter to convert given timestamp to format.""" """Filter to convert given timestamp to format."""
try: try:
@ -508,6 +517,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment):
ENV = TemplateEnvironment() ENV = TemplateEnvironment()
ENV.filters['round'] = forgiving_round ENV.filters['round'] = forgiving_round
ENV.filters['multiply'] = multiply ENV.filters['multiply'] = multiply
ENV.filters['log'] = logarithm
ENV.filters['timestamp_custom'] = timestamp_custom ENV.filters['timestamp_custom'] = timestamp_custom
ENV.filters['timestamp_local'] = timestamp_local ENV.filters['timestamp_local'] = timestamp_local
ENV.filters['timestamp_utc'] = timestamp_utc ENV.filters['timestamp_utc'] = timestamp_utc
@ -515,6 +525,7 @@ ENV.filters['is_defined'] = fail_when_undefined
ENV.filters['max'] = max ENV.filters['max'] = max
ENV.filters['min'] = min ENV.filters['min'] = min
ENV.filters['random'] = random_every_time ENV.filters['random'] = random_every_time
ENV.globals['log'] = logarithm
ENV.globals['float'] = forgiving_float ENV.globals['float'] = forgiving_float
ENV.globals['now'] = dt_util.now ENV.globals['now'] = dt_util.now
ENV.globals['utcnow'] = dt_util.utcnow ENV.globals['utcnow'] = dt_util.utcnow

View File

@ -3,6 +3,7 @@ import asyncio
from datetime import datetime from datetime import datetime
import unittest import unittest
import random import random
import math
from unittest.mock import patch from unittest.mock import patch
from homeassistant.components import group from homeassistant.components import group
@ -125,6 +126,29 @@ class TestHelpersTemplate(unittest.TestCase):
template.Template('{{ %s | multiply(10) | round }}' % inp, template.Template('{{ %s | multiply(10) | round }}' % inp,
self.hass).render()) self.hass).render())
def test_logarithm(self):
"""Test logarithm."""
tests = [
(4, 2, '2.0'),
(1000, 10, '3.0'),
(math.e, '', '1.0'),
('"invalid"', '_', 'invalid'),
(10, '"invalid"', '10.0'),
]
for value, base, expected in tests:
self.assertEqual(
expected,
template.Template(
'{{ %s | log(%s) | round(1) }}' % (value, base),
self.hass).render())
self.assertEqual(
expected,
template.Template(
'{{ log(%s, %s) | round(1) }}' % (value, base),
self.hass).render())
def test_strptime(self): def test_strptime(self):
"""Test the parse timestamp method.""" """Test the parse timestamp method."""
tests = [ tests = [