Add optional default value to average template function/filter (#77499)

* Return None on empty list

* Updated to use default value

* Update comment.
This commit is contained in:
ehendrix23 2022-10-03 02:07:19 -06:00 committed by GitHub
parent 61f0d0ea15
commit 47b40e1e61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 6 deletions

View File

@ -1657,7 +1657,7 @@ def min_max_from_filter(builtin_filter: Any, name: str) -> Any:
return pass_environment(wrapper) return pass_environment(wrapper)
def average(*args: Any) -> float: def average(*args: Any, default: Any = _SENTINEL) -> Any:
""" """
Filter and function to calculate the arithmetic mean of an iterable or of two or more arguments. Filter and function to calculate the arithmetic mean of an iterable or of two or more arguments.
@ -1666,13 +1666,23 @@ def average(*args: Any) -> float:
if len(args) == 0: if len(args) == 0:
raise TypeError("average expected at least 1 argument, got 0") raise TypeError("average expected at least 1 argument, got 0")
if len(args) == 1: # If first argument is iterable and more then 1 argument provided but not a named default,
# then use 2nd argument as default.
if isinstance(args[0], Iterable): if isinstance(args[0], Iterable):
return statistics.fmean(args[0]) average_list = args[0]
if len(args) > 1 and default is _SENTINEL:
default = args[1]
elif len(args) == 1:
raise TypeError(f"'{type(args[0]).__name__}' object is not iterable") raise TypeError(f"'{type(args[0]).__name__}' object is not iterable")
else:
average_list = args
return statistics.fmean(args) try:
return statistics.fmean(average_list)
except (TypeError, statistics.StatisticsError):
if default is _SENTINEL:
raise_no_default("average", args)
return default
def forgiving_float(value, default=_SENTINEL): def forgiving_float(value, default=_SENTINEL):

View File

@ -973,12 +973,27 @@ def test_average(hass):
assert template.Template("{{ average([1, 2, 3]) }}", hass).async_render() == 2 assert template.Template("{{ average([1, 2, 3]) }}", hass).async_render() == 2
assert template.Template("{{ average(1, 2, 3) }}", hass).async_render() == 2 assert template.Template("{{ average(1, 2, 3) }}", hass).async_render() == 2
# Testing of default values
assert template.Template("{{ average([1, 2, 3], -1) }}", hass).async_render() == 2
assert template.Template("{{ average([], -1) }}", hass).async_render() == -1
assert template.Template("{{ average([], default=-1) }}", hass).async_render() == -1
assert (
template.Template("{{ average([], 5, default=-1) }}", hass).async_render() == -1
)
assert (
template.Template("{{ average(1, 'a', 3, default=-1) }}", hass).async_render()
== -1
)
with pytest.raises(TemplateError): with pytest.raises(TemplateError):
template.Template("{{ 1 | average }}", hass).async_render() template.Template("{{ 1 | average }}", hass).async_render()
with pytest.raises(TemplateError): with pytest.raises(TemplateError):
template.Template("{{ average() }}", hass).async_render() template.Template("{{ average() }}", hass).async_render()
with pytest.raises(TemplateError):
template.Template("{{ average([]) }}", hass).async_render()
def test_min(hass): def test_min(hass):
"""Test the min filter.""" """Test the min filter."""