diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 9cdcfade9ec134ec22cb2ea4a1ed9fd94dd4766f..993deae280a330b5162caae91ffc12f44d6766af 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -7,6 +7,7 @@ from contextlib import suppress from dataclasses import dataclass from datetime import UTC, date, datetime, timedelta from decimal import Decimal, InvalidOperation as DecimalInvalidOperation +from functools import partial import logging from math import ceil, floor, isfinite, log10 from typing import Any, Final, Self, cast, final @@ -57,6 +58,10 @@ from homeassistant.helpers.config_validation import ( PLATFORM_SCHEMA, PLATFORM_SCHEMA_BASE, ) +from homeassistant.helpers.deprecation import ( + check_if_deprecated_constant, + dir_with_deprecated_constants, +) from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_platform import EntityPlatform @@ -66,6 +71,9 @@ from homeassistant.util import dt as dt_util from homeassistant.util.enum import try_parse_enum from .const import ( # noqa: F401 + _DEPRECATED_STATE_CLASS_MEASUREMENT, + _DEPRECATED_STATE_CLASS_TOTAL, + _DEPRECATED_STATE_CLASS_TOTAL_INCREASING, ATTR_LAST_RESET, ATTR_OPTIONS, ATTR_STATE_CLASS, @@ -76,9 +84,6 @@ from .const import ( # noqa: F401 DEVICE_CLASSES_SCHEMA, DOMAIN, NON_NUMERIC_DEVICE_CLASSES, - STATE_CLASS_MEASUREMENT, - STATE_CLASS_TOTAL, - STATE_CLASS_TOTAL_INCREASING, STATE_CLASSES, STATE_CLASSES_SCHEMA, UNIT_CONVERTERS, @@ -110,6 +115,12 @@ __all__ = [ "SensorStateClass", ] +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# Both can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) + # mypy: disallow-any-generics diff --git a/homeassistant/components/sensor/const.py b/homeassistant/components/sensor/const.py index e8b1742f31593a9e422c22b0c0454615ad03341d..d57a09981efba752a9cf8bd4df9a9797e3f7b8b2 100644 --- a/homeassistant/components/sensor/const.py +++ b/homeassistant/components/sensor/const.py @@ -2,6 +2,7 @@ from __future__ import annotations from enum import StrEnum +from functools import partial from typing import Final import voluptuous as vol @@ -35,6 +36,11 @@ from homeassistant.const import ( UnitOfVolume, UnitOfVolumetricFlux, ) +from homeassistant.helpers.deprecation import ( + DeprecatedConstantEnum, + check_if_deprecated_constant, + dir_with_deprecated_constants, +) from homeassistant.util.unit_conversion import ( BaseUnitConverter, DataRateConverter, @@ -451,11 +457,21 @@ STATE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.Coerce(SensorStateClass)) # STATE_CLASS* is deprecated as of 2021.12 # use the SensorStateClass enum instead. -STATE_CLASS_MEASUREMENT: Final = "measurement" -STATE_CLASS_TOTAL: Final = "total" -STATE_CLASS_TOTAL_INCREASING: Final = "total_increasing" +_DEPRECATED_STATE_CLASS_MEASUREMENT: Final = DeprecatedConstantEnum( + SensorStateClass.MEASUREMENT, "2025.1" +) +_DEPRECATED_STATE_CLASS_TOTAL: Final = DeprecatedConstantEnum( + SensorStateClass.TOTAL, "2025.1" +) +_DEPRECATED_STATE_CLASS_TOTAL_INCREASING: Final = DeprecatedConstantEnum( + SensorStateClass.TOTAL_INCREASING, "2025.1" +) STATE_CLASSES: Final[list[str]] = [cls.value for cls in SensorStateClass] +# Both can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) + UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = { SensorDeviceClass.ATMOSPHERIC_PRESSURE: PressureConverter, SensorDeviceClass.CURRENT: ElectricCurrentConverter, diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index 9164bb442c3f496c70ff1cae5abdd831447af536..2940d76f0a61fdb2198dfa4143c2eb22e22fef67 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -4,10 +4,12 @@ from __future__ import annotations from collections.abc import Generator from datetime import UTC, date, datetime from decimal import Decimal +from types import ModuleType from typing import Any import pytest +from homeassistant.components import sensor from homeassistant.components.number import NumberDeviceClass from homeassistant.components.sensor import ( DEVICE_CLASS_STATE_CLASSES, @@ -50,6 +52,7 @@ from tests.common import ( MockModule, MockPlatform, async_mock_restore_state_shutdown_restart, + import_and_test_deprecated_constant_enum, mock_config_flow, mock_integration, mock_platform, @@ -2519,3 +2522,16 @@ async def test_entity_category_config_raises_error( ) assert not hass.states.get("sensor.test") + + +@pytest.mark.parametrize(("enum"), list(sensor.SensorStateClass)) +@pytest.mark.parametrize(("module"), [sensor, sensor.const]) +def test_deprecated_constants( + caplog: pytest.LogCaptureFixture, + enum: sensor.SensorStateClass, + module: ModuleType, +) -> None: + """Test deprecated constants.""" + import_and_test_deprecated_constant_enum( + caplog, module, enum, "STATE_CLASS_", "2025.1" + )