Don't allow numerical sensor state to be NaN or inf (#98110)

pull/98880/head
Erik Montnemery 2023-08-23 14:16:40 +02:00 committed by GitHub
parent 3b16a3e1e0
commit e3b945a8d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 9 deletions

View File

@ -8,7 +8,7 @@ from dataclasses import dataclass
from datetime import UTC, date, datetime, timedelta
from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
import logging
from math import ceil, floor, log10
from math import ceil, floor, isfinite, log10
from typing import Any, Final, Self, cast, final
from homeassistant.config_entries import ConfigEntry
@ -582,7 +582,11 @@ class SensorEntity(Entity):
if not isinstance(value, (int, float, Decimal)):
try:
if isinstance(value, str) and "." not in value and "e" not in value:
numerical_value = int(value)
try:
numerical_value = int(value)
except ValueError:
# Handle nan, inf
numerical_value = float(value)
else:
numerical_value = float(value) # type:ignore[arg-type]
except (TypeError, ValueError) as err:
@ -596,6 +600,15 @@ class SensorEntity(Entity):
else:
numerical_value = value
if not isfinite(numerical_value):
raise ValueError(
f"Sensor {self.entity_id} has device class '{device_class}', "
f"state class '{state_class}' unit '{unit_of_measurement}' and "
f"suggested precision '{suggested_precision}' thus indicating it "
f"has a numeric value; however, it has the non-finite value: "
f"'{numerical_value}'"
)
if native_unit_of_measurement != unit_of_measurement and (
converter := UNIT_CONVERTERS.get(device_class)
):

View File

@ -1861,13 +1861,17 @@ async def test_device_classes_with_invalid_unit_of_measurement(
],
)
@pytest.mark.parametrize(
"native_value",
("native_value", "problem"),
[
"",
"abc",
"13.7.1",
datetime(2012, 11, 10, 7, 35, 1),
date(2012, 11, 10),
("", "non-numeric"),
("abc", "non-numeric"),
("13.7.1", "non-numeric"),
(datetime(2012, 11, 10, 7, 35, 1), "non-numeric"),
(date(2012, 11, 10), "non-numeric"),
("inf", "non-finite"),
(float("inf"), "non-finite"),
("nan", "non-finite"),
(float("nan"), "non-finite"),
],
)
async def test_non_numeric_validation_error(
@ -1875,6 +1879,7 @@ async def test_non_numeric_validation_error(
caplog: pytest.LogCaptureFixture,
enable_custom_integrations: None,
native_value: Any,
problem: str,
device_class: SensorDeviceClass | None,
state_class: SensorStateClass | None,
unit: str | None,
@ -1899,7 +1904,7 @@ async def test_non_numeric_validation_error(
assert (
"thus indicating it has a numeric value; "
f"however, it has the non-numeric value: '{native_value}'"
f"however, it has the {problem} value: '{native_value}'"
) in caplog.text