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)
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.
@ -1666,13 +1666,23 @@ def average(*args: Any) -> float:
if len(args) == 0:
raise TypeError("average expected at least 1 argument, got 0")
if len(args) == 1:
if isinstance(args[0], Iterable):
return statistics.fmean(args[0])
# 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):
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")
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):

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
# 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):
template.Template("{{ 1 | average }}", hass).async_render()
with pytest.raises(TemplateError):
template.Template("{{ average() }}", hass).async_render()
with pytest.raises(TemplateError):
template.Template("{{ average([]) }}", hass).async_render()
def test_min(hass):
"""Test the min filter."""