Deprecate deprecated climate constants (#106096)

This commit is contained in:
Robert Resch 2023-12-21 00:00:21 +01:00 committed by GitHub
parent dfb08e7efd
commit 494a897568
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 150 additions and 65 deletions

View file

@ -26,6 +26,10 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA_BASE, PLATFORM_SCHEMA_BASE,
make_entity_service_schema, make_entity_service_schema,
) )
from homeassistant.helpers.deprecation import (
check_if_deprecated_constant,
dir_with_deprecated_constants,
)
from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.temperature import display_temp as show_temp from homeassistant.helpers.temperature import display_temp as show_temp
@ -33,6 +37,20 @@ from homeassistant.helpers.typing import ConfigType
from homeassistant.util.unit_conversion import TemperatureConverter from homeassistant.util.unit_conversion import TemperatureConverter
from .const import ( # noqa: F401 from .const import ( # noqa: F401
_DEPRECATED_HVAC_MODE_AUTO,
_DEPRECATED_HVAC_MODE_COOL,
_DEPRECATED_HVAC_MODE_DRY,
_DEPRECATED_HVAC_MODE_FAN_ONLY,
_DEPRECATED_HVAC_MODE_HEAT,
_DEPRECATED_HVAC_MODE_HEAT_COOL,
_DEPRECATED_HVAC_MODE_OFF,
_DEPRECATED_SUPPORT_AUX_HEAT,
_DEPRECATED_SUPPORT_FAN_MODE,
_DEPRECATED_SUPPORT_PRESET_MODE,
_DEPRECATED_SUPPORT_SWING_MODE,
_DEPRECATED_SUPPORT_TARGET_HUMIDITY,
_DEPRECATED_SUPPORT_TARGET_TEMPERATURE,
_DEPRECATED_SUPPORT_TARGET_TEMPERATURE_RANGE,
ATTR_AUX_HEAT, ATTR_AUX_HEAT,
ATTR_CURRENT_HUMIDITY, ATTR_CURRENT_HUMIDITY,
ATTR_CURRENT_TEMPERATURE, ATTR_CURRENT_TEMPERATURE,
@ -64,10 +82,6 @@ from .const import ( # noqa: F401
FAN_OFF, FAN_OFF,
FAN_ON, FAN_ON,
FAN_TOP, FAN_TOP,
HVAC_MODE_COOL,
HVAC_MODE_HEAT,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
HVAC_MODES, HVAC_MODES,
PRESET_ACTIVITY, PRESET_ACTIVITY,
PRESET_AWAY, PRESET_AWAY,
@ -84,13 +98,6 @@ from .const import ( # noqa: F401
SERVICE_SET_PRESET_MODE, SERVICE_SET_PRESET_MODE,
SERVICE_SET_SWING_MODE, SERVICE_SET_SWING_MODE,
SERVICE_SET_TEMPERATURE, SERVICE_SET_TEMPERATURE,
SUPPORT_AUX_HEAT,
SUPPORT_FAN_MODE,
SUPPORT_PRESET_MODE,
SUPPORT_SWING_MODE,
SUPPORT_TARGET_HUMIDITY,
SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE,
SWING_BOTH, SWING_BOTH,
SWING_HORIZONTAL, SWING_HORIZONTAL,
SWING_OFF, SWING_OFF,
@ -128,6 +135,12 @@ SET_TEMPERATURE_SCHEMA = vol.All(
), ),
) )
# 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__ = ft.partial(check_if_deprecated_constant, module_globals=globals())
__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals())
# mypy: disallow-any-generics # mypy: disallow-any-generics

View file

@ -1,6 +1,13 @@
"""Provides the constants needed for component.""" """Provides the constants needed for component."""
from enum import IntFlag, StrEnum from enum import IntFlag, StrEnum
from functools import partial
from homeassistant.helpers.deprecation import (
DeprecatedConstantEnum,
check_if_deprecated_constant,
dir_with_deprecated_constants,
)
class HVACMode(StrEnum): class HVACMode(StrEnum):
@ -31,13 +38,13 @@ class HVACMode(StrEnum):
# These HVAC_MODE_* constants are deprecated as of Home Assistant 2022.5. # These HVAC_MODE_* constants are deprecated as of Home Assistant 2022.5.
# Please use the HVACMode enum instead. # Please use the HVACMode enum instead.
HVAC_MODE_OFF = "off" _DEPRECATED_HVAC_MODE_OFF = DeprecatedConstantEnum(HVACMode.OFF, "2025.1")
HVAC_MODE_HEAT = "heat" _DEPRECATED_HVAC_MODE_HEAT = DeprecatedConstantEnum(HVACMode.HEAT, "2025.1")
HVAC_MODE_COOL = "cool" _DEPRECATED_HVAC_MODE_COOL = DeprecatedConstantEnum(HVACMode.COOL, "2025.1")
HVAC_MODE_HEAT_COOL = "heat_cool" _DEPRECATED_HVAC_MODE_HEAT_COOL = DeprecatedConstantEnum(HVACMode.HEAT_COOL, "2025.1")
HVAC_MODE_AUTO = "auto" _DEPRECATED_HVAC_MODE_AUTO = DeprecatedConstantEnum(HVACMode.AUTO, "2025.1")
HVAC_MODE_DRY = "dry" _DEPRECATED_HVAC_MODE_DRY = DeprecatedConstantEnum(HVACMode.DRY, "2025.1")
HVAC_MODE_FAN_ONLY = "fan_only" _DEPRECATED_HVAC_MODE_FAN_ONLY = DeprecatedConstantEnum(HVACMode.FAN_ONLY, "2025.1")
HVAC_MODES = [cls.value for cls in HVACMode] HVAC_MODES = [cls.value for cls in HVACMode]
# No preset is active # No preset is active
@ -99,12 +106,12 @@ class HVACAction(StrEnum):
# These CURRENT_HVAC_* constants are deprecated as of Home Assistant 2022.5. # These CURRENT_HVAC_* constants are deprecated as of Home Assistant 2022.5.
# Please use the HVACAction enum instead. # Please use the HVACAction enum instead.
CURRENT_HVAC_OFF = "off" _DEPRECATED_CURRENT_HVAC_OFF = DeprecatedConstantEnum(HVACAction.OFF, "2025.1")
CURRENT_HVAC_HEAT = "heating" _DEPRECATED_CURRENT_HVAC_HEAT = DeprecatedConstantEnum(HVACAction.HEATING, "2025.1")
CURRENT_HVAC_COOL = "cooling" _DEPRECATED_CURRENT_HVAC_COOL = DeprecatedConstantEnum(HVACAction.COOLING, "2025.1")
CURRENT_HVAC_DRY = "drying" _DEPRECATED_CURRENT_HVAC_DRY = DeprecatedConstantEnum(HVACAction.DRYING, "2025.1")
CURRENT_HVAC_IDLE = "idle" _DEPRECATED_CURRENT_HVAC_IDLE = DeprecatedConstantEnum(HVACAction.IDLE, "2025.1")
CURRENT_HVAC_FAN = "fan" _DEPRECATED_CURRENT_HVAC_FAN = DeprecatedConstantEnum(HVACAction.FAN, "2025.1")
CURRENT_HVAC_ACTIONS = [cls.value for cls in HVACAction] CURRENT_HVAC_ACTIONS = [cls.value for cls in HVACAction]
@ -159,10 +166,28 @@ class ClimateEntityFeature(IntFlag):
# These SUPPORT_* constants are deprecated as of Home Assistant 2022.5. # These SUPPORT_* constants are deprecated as of Home Assistant 2022.5.
# Please use the ClimateEntityFeature enum instead. # Please use the ClimateEntityFeature enum instead.
SUPPORT_TARGET_TEMPERATURE = 1 _DEPRECATED_SUPPORT_TARGET_TEMPERATURE = DeprecatedConstantEnum(
SUPPORT_TARGET_TEMPERATURE_RANGE = 2 ClimateEntityFeature.TARGET_TEMPERATURE, "2025.1"
SUPPORT_TARGET_HUMIDITY = 4 )
SUPPORT_FAN_MODE = 8 _DEPRECATED_SUPPORT_TARGET_TEMPERATURE_RANGE = DeprecatedConstantEnum(
SUPPORT_PRESET_MODE = 16 ClimateEntityFeature.TARGET_TEMPERATURE_RANGE, "2025.1"
SUPPORT_SWING_MODE = 32 )
SUPPORT_AUX_HEAT = 64 _DEPRECATED_SUPPORT_TARGET_HUMIDITY = DeprecatedConstantEnum(
ClimateEntityFeature.TARGET_HUMIDITY, "2025.1"
)
_DEPRECATED_SUPPORT_FAN_MODE = DeprecatedConstantEnum(
ClimateEntityFeature.FAN_MODE, "2025.1"
)
_DEPRECATED_SUPPORT_PRESET_MODE = DeprecatedConstantEnum(
ClimateEntityFeature.PRESET_MODE, "2025.1"
)
_DEPRECATED_SUPPORT_SWING_MODE = DeprecatedConstantEnum(
ClimateEntityFeature.SWING_MODE, "2025.1"
)
_DEPRECATED_SUPPORT_AUX_HEAT = DeprecatedConstantEnum(
ClimateEntityFeature.AUX_HEAT, "2025.1"
)
# 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())

View file

@ -72,7 +72,7 @@ async def async_get_actions(
} }
actions.append({**base_action, CONF_TYPE: "set_hvac_mode"}) actions.append({**base_action, CONF_TYPE: "set_hvac_mode"})
if supported_features & const.SUPPORT_PRESET_MODE: if supported_features & const.ClimateEntityFeature.PRESET_MODE:
actions.append({**base_action, CONF_TYPE: "set_preset_mode"}) actions.append({**base_action, CONF_TYPE: "set_preset_mode"})
return actions return actions

View file

@ -71,7 +71,7 @@ async def async_get_conditions(
conditions.append({**base_condition, CONF_TYPE: "is_hvac_mode"}) conditions.append({**base_condition, CONF_TYPE: "is_hvac_mode"})
if supported_features & const.SUPPORT_PRESET_MODE: if supported_features & const.ClimateEntityFeature.PRESET_MODE:
conditions.append({**base_condition, CONF_TYPE: "is_preset_mode"}) conditions.append({**base_condition, CONF_TYPE: "is_preset_mode"})
return conditions return conditions

View file

@ -220,7 +220,7 @@ async def test_action(
assert set_hvac_mode_calls[0].service == "set_hvac_mode" assert set_hvac_mode_calls[0].service == "set_hvac_mode"
assert set_hvac_mode_calls[0].data == { assert set_hvac_mode_calls[0].data == {
"entity_id": entry.entity_id, "entity_id": entry.entity_id,
"hvac_mode": const.HVAC_MODE_OFF, "hvac_mode": const.HVACMode.OFF,
} }
assert set_preset_mode_calls[0].domain == DOMAIN assert set_preset_mode_calls[0].domain == DOMAIN
assert set_preset_mode_calls[0].service == "set_preset_mode" assert set_preset_mode_calls[0].service == "set_preset_mode"
@ -287,7 +287,7 @@ async def test_action_legacy(
assert set_hvac_mode_calls[0].service == "set_hvac_mode" assert set_hvac_mode_calls[0].service == "set_hvac_mode"
assert set_hvac_mode_calls[0].data == { assert set_hvac_mode_calls[0].data == {
"entity_id": entry.entity_id, "entity_id": entry.entity_id,
"hvac_mode": const.HVAC_MODE_OFF, "hvac_mode": const.HVACMode.OFF,
} }

View file

@ -1,11 +1,14 @@
"""The tests for the climate component.""" """The tests for the climate component."""
from __future__ import annotations from __future__ import annotations
from enum import Enum
from types import ModuleType
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
import voluptuous as vol import voluptuous as vol
from homeassistant.components import climate
from homeassistant.components.climate import ( from homeassistant.components.climate import (
SET_TEMPERATURE_SCHEMA, SET_TEMPERATURE_SCHEMA,
ClimateEntity, ClimateEntity,
@ -13,7 +16,11 @@ from homeassistant.components.climate import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from tests.common import async_mock_service from tests.common import (
async_mock_service,
import_and_test_deprecated_constant,
import_and_test_deprecated_constant_enum,
)
async def test_set_temp_schema_no_req( async def test_set_temp_schema_no_req(
@ -96,3 +103,58 @@ async def test_sync_turn_off(hass: HomeAssistant) -> None:
await climate.async_turn_off() await climate.async_turn_off()
assert climate.turn_off.called assert climate.turn_off.called
def _create_tuples(enum: Enum, constant_prefix: str) -> list[tuple[Enum, str]]:
result = []
for enum in enum:
result.append((enum, constant_prefix))
return result
@pytest.mark.parametrize(
("enum", "constant_prefix"),
_create_tuples(climate.ClimateEntityFeature, "SUPPORT_")
+ _create_tuples(climate.HVACMode, "HVAC_MODE_"),
)
@pytest.mark.parametrize(
"module",
[climate, climate.const],
)
def test_deprecated_constants(
caplog: pytest.LogCaptureFixture,
enum: Enum,
constant_prefix: str,
module: ModuleType,
) -> None:
"""Test deprecated constants."""
import_and_test_deprecated_constant_enum(
caplog, module, enum, constant_prefix, "2025.1"
)
@pytest.mark.parametrize(
("enum", "constant_postfix"),
[
(climate.HVACAction.OFF, "OFF"),
(climate.HVACAction.HEATING, "HEAT"),
(climate.HVACAction.COOLING, "COOL"),
(climate.HVACAction.DRYING, "DRY"),
(climate.HVACAction.IDLE, "IDLE"),
(climate.HVACAction.FAN, "FAN"),
],
)
def test_deprecated_current_constants(
caplog: pytest.LogCaptureFixture,
enum: climate.HVACAction,
constant_postfix: str,
) -> None:
"""Test deprecated current constants."""
import_and_test_deprecated_constant(
caplog,
climate.const,
"CURRENT_HVAC_" + constant_postfix,
f"{enum.__class__.__name__}.{enum.name}",
enum,
"2025.1",
)

View file

@ -8,11 +8,7 @@ from unittest import mock
from aiohomekit import AccessoryNotFoundError from aiohomekit import AccessoryNotFoundError
from aiohomekit.testing import FakePairing from aiohomekit.testing import FakePairing
from homeassistant.components.climate import ( from homeassistant.components.climate import ClimateEntityFeature
SUPPORT_TARGET_HUMIDITY,
SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE,
)
from homeassistant.components.sensor import SensorStateClass from homeassistant.components.sensor import SensorStateClass
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import UnitOfTemperature from homeassistant.const import UnitOfTemperature
@ -108,9 +104,9 @@ async def test_ecobee3_setup(hass: HomeAssistant) -> None:
friendly_name="HomeW", friendly_name="HomeW",
unique_id="00:00:00:00:00:00_1_16", unique_id="00:00:00:00:00:00_1_16",
supported_features=( supported_features=(
SUPPORT_TARGET_TEMPERATURE ClimateEntityFeature.TARGET_TEMPERATURE
| SUPPORT_TARGET_TEMPERATURE_RANGE | ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| SUPPORT_TARGET_HUMIDITY | ClimateEntityFeature.TARGET_HUMIDITY
), ),
capabilities={ capabilities={
"hvac_modes": ["off", "heat", "cool", "heat_cool"], "hvac_modes": ["off", "heat", "cool", "heat_cool"],

View file

@ -6,18 +6,7 @@ from matter_server.client.models.node import MatterNode
from matter_server.common.helpers.util import create_attribute_path_from_attribute from matter_server.common.helpers.util import create_attribute_path_from_attribute
import pytest import pytest
from homeassistant.components.climate import ( from homeassistant.components.climate import HVACAction, HVACMode
HVAC_MODE_COOL,
HVAC_MODE_HEAT,
HVAC_MODE_HEAT_COOL,
HVACAction,
HVACMode,
)
from homeassistant.components.climate.const import (
HVAC_MODE_DRY,
HVAC_MODE_FAN_ONLY,
HVAC_MODE_OFF,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .common import ( from .common import (
@ -51,7 +40,7 @@ async def test_thermostat(
# test set temperature when target temp is None # test set temperature when target temp is None
assert state.attributes["temperature"] is None assert state.attributes["temperature"] is None
assert state.state == HVAC_MODE_COOL assert state.state == HVACMode.COOL
with pytest.raises( with pytest.raises(
ValueError, match="Current target_temperature should not be None" ValueError, match="Current target_temperature should not be None"
): ):
@ -85,7 +74,7 @@ async def test_thermostat(
): ):
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_HEAT_COOL assert state.state == HVACMode.HEAT_COOL
await hass.services.async_call( await hass.services.async_call(
"climate", "climate",
"set_temperature", "set_temperature",
@ -119,19 +108,19 @@ async def test_thermostat(
await trigger_subscription_callback(hass, matter_client) await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_OFF assert state.state == HVACMode.OFF
set_node_attribute(thermostat, 1, 513, 28, 7) set_node_attribute(thermostat, 1, 513, 28, 7)
await trigger_subscription_callback(hass, matter_client) await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_FAN_ONLY assert state.state == HVACMode.FAN_ONLY
set_node_attribute(thermostat, 1, 513, 28, 8) set_node_attribute(thermostat, 1, 513, 28, 8)
await trigger_subscription_callback(hass, matter_client) await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_DRY assert state.state == HVACMode.DRY
# test running state update from device # test running state update from device
set_node_attribute(thermostat, 1, 513, 41, 1) set_node_attribute(thermostat, 1, 513, 41, 1)
@ -188,7 +177,7 @@ async def test_thermostat(
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_HEAT assert state.state == HVACMode.HEAT
# change occupied heating setpoint to 20 # change occupied heating setpoint to 20
set_node_attribute(thermostat, 1, 513, 18, 2000) set_node_attribute(thermostat, 1, 513, 18, 2000)
@ -225,7 +214,7 @@ async def test_thermostat(
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_COOL assert state.state == HVACMode.COOL
# change occupied cooling setpoint to 18 # change occupied cooling setpoint to 18
set_node_attribute(thermostat, 1, 513, 17, 1800) set_node_attribute(thermostat, 1, 513, 17, 1800)
@ -273,7 +262,7 @@ async def test_thermostat(
state = hass.states.get("climate.longan_link_hvac") state = hass.states.get("climate.longan_link_hvac")
assert state assert state
assert state.state == HVAC_MODE_HEAT_COOL assert state.state == HVACMode.HEAT_COOL
# change occupied cooling setpoint to 18 # change occupied cooling setpoint to 18
set_node_attribute(thermostat, 1, 513, 17, 2500) set_node_attribute(thermostat, 1, 513, 17, 2500)
@ -340,7 +329,7 @@ async def test_thermostat(
"set_hvac_mode", "set_hvac_mode",
{ {
"entity_id": "climate.longan_link_hvac", "entity_id": "climate.longan_link_hvac",
"hvac_mode": HVAC_MODE_HEAT, "hvac_mode": HVACMode.HEAT,
}, },
blocking=True, blocking=True,
) )