1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-15 07:36:16 +00:00

Raise error when light reports an invalid color_mode (#162620)

This commit is contained in:
epenet
2026-02-09 14:18:37 +01:00
committed by GitHub
parent e87056408e
commit f6e0bc28f4
2 changed files with 41 additions and 45 deletions

View File

@@ -952,8 +952,8 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def __validate_color_mode(
self,
color_mode: ColorMode | str | None,
supported_color_modes: set[ColorMode] | set[str],
color_mode: ColorMode | None,
supported_color_modes: set[ColorMode],
effect: str | None,
) -> None:
"""Validate the color mode."""
@@ -966,23 +966,10 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
# color modes
if color_mode in supported_color_modes:
return
# Warning added in 2024.3, reject in 2025.3
if not self.__color_mode_reported and self.__should_report_light_issue():
self.__color_mode_reported = True
report_issue = self._suggest_report_issue()
_LOGGER.warning(
(
"%s (%s) set to unsupported color mode %s, expected one of %s, "
"this will stop working in Home Assistant Core 2025.3, "
"please %s"
),
self.entity_id,
type(self),
color_mode,
supported_color_modes,
report_issue,
)
return
raise HomeAssistantError(
f"{self.entity_id} ({type(self)}) set to unsupported color mode "
f"{color_mode}, expected one of {supported_color_modes}"
)
# When an effect is active, the color mode should indicate what adjustments are
# supported by the effect. To make this possible, we allow the light to set its
@@ -995,23 +982,11 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if color_mode in effect_color_modes:
return
# Warning added in 2024.3, reject in 2025.3
if not self.__color_mode_reported and self.__should_report_light_issue():
self.__color_mode_reported = True
report_issue = self._suggest_report_issue()
_LOGGER.warning(
(
"%s (%s) set to unsupported color mode %s when rendering an effect,"
" expected one of %s, this will stop working in Home Assistant "
"Core 2025.3, please %s"
),
self.entity_id,
type(self),
color_mode,
effect_color_modes,
report_issue,
)
return
raise HomeAssistantError(
f"{self.entity_id} ({type(self)}) set to unsupported color mode "
f"{color_mode} when rendering an effect, expected one "
f"of {effect_color_modes}"
)
def __validate_supported_color_modes(
self,
@@ -1053,11 +1028,11 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
_is_on = self.is_on
color_mode = self.color_mode if _is_on else None
effect: str | None
effect: str | None = None
if LightEntityFeature.EFFECT in supported_features:
data[ATTR_EFFECT] = effect = self.effect if _is_on else None
else:
effect = None
if _is_on:
effect = self.effect
data[ATTR_EFFECT] = effect
self.__validate_color_mode(color_mode, legacy_supported_color_modes, effect)

View File

@@ -129,7 +129,9 @@ async def test_services(
ent1, ent2, ent3 = mock_light_entities
ent1.supported_color_modes = [light.ColorMode.HS]
ent1.color_mode = light.ColorMode.HS
ent3.supported_color_modes = [light.ColorMode.HS]
ent3.color_mode = light.ColorMode.HS
ent1.supported_features = light.LightEntityFeature.TRANSITION
ent2.supported_features = (
light.LightEntityFeature.EFFECT | light.LightEntityFeature.TRANSITION
@@ -539,6 +541,7 @@ async def test_light_profiles(
ent1, _, _ = mock_light_entities
ent1.supported_color_modes = [light.ColorMode.HS]
ent1.color_mode = light.ColorMode.HS
ent1.supported_features = light.LightEntityFeature.TRANSITION
await hass.services.async_call(
@@ -1140,6 +1143,7 @@ async def test_light_service_call_rgbw(hass: HomeAssistant) -> None:
"""Test rgbw functionality in service calls."""
entity0 = MockLight("Test_rgbw", STATE_ON)
entity0.supported_color_modes = {light.ColorMode.RGBW}
entity0.color_mode = light.ColorMode.RGBW
setup_test_component_platform(hass, light.DOMAIN, [entity0])
@@ -1309,12 +1313,15 @@ async def test_light_service_call_color_conversion(hass: HomeAssistant) -> None:
entity0 = entities[0]
entity0.supported_color_modes = {light.ColorMode.HS}
entity0.color_mode = light.ColorMode.HS
entity1 = entities[1]
entity1.supported_color_modes = {light.ColorMode.RGB}
entity1.color_mode = light.ColorMode.RGB
entity2 = entities[2]
entity2.supported_color_modes = {light.ColorMode.XY}
entity2.color_mode = light.ColorMode.XY
entity3 = entities[3]
entity3.supported_color_modes = {
@@ -1322,15 +1329,19 @@ async def test_light_service_call_color_conversion(hass: HomeAssistant) -> None:
light.ColorMode.RGB,
light.ColorMode.XY,
}
entity3.color_mode = light.ColorMode.HS
entity4 = entities[4]
entity4.supported_color_modes = {light.ColorMode.RGBW}
entity4.color_mode = light.ColorMode.RGBW
entity5 = entities[5]
entity5.supported_color_modes = {light.ColorMode.RGBWW}
entity5.color_mode = light.ColorMode.RGBWW
entity6 = entities[6]
entity6.supported_color_modes = {light.ColorMode.COLOR_TEMP}
entity6.color_mode = light.ColorMode.COLOR_TEMP
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
await hass.async_block_till_done()
@@ -1778,12 +1789,15 @@ async def test_light_service_call_color_temp_emulation(hass: HomeAssistant) -> N
entity0 = entities[0]
entity0.supported_color_modes = {light.ColorMode.COLOR_TEMP, light.ColorMode.HS}
entity0.color_mode = light.ColorMode.COLOR_TEMP
entity1 = entities[1]
entity1.supported_color_modes = {light.ColorMode.HS}
entity1.color_mode = light.ColorMode.HS
entity2 = entities[2]
entity2.supported_color_modes = {light.ColorMode.HS, light.ColorMode.WHITE}
entity2.color_mode = light.ColorMode.HS
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
await hass.async_block_till_done()
@@ -1838,9 +1852,11 @@ async def test_light_service_call_color_temp_conversion(hass: HomeAssistant) ->
light.ColorMode.COLOR_TEMP,
light.ColorMode.RGBWW,
}
entity0.color_mode = light.ColorMode.COLOR_TEMP
entity1 = entities[1]
entity1.supported_color_modes = {light.ColorMode.RGBWW}
entity1.color_mode = light.ColorMode.RGBWW
assert entity1.min_color_temp_kelvin == 2000
assert entity1.max_color_temp_kelvin == 6535
@@ -1956,6 +1972,7 @@ async def test_light_service_call_white_mode(hass: HomeAssistant) -> None:
"""Test color_mode white in service calls."""
entity0 = MockLight("Test_white", STATE_ON)
entity0.supported_color_modes = {light.ColorMode.HS, light.ColorMode.WHITE}
entity0.color_mode = light.ColorMode.HS
setup_test_component_platform(hass, light.DOMAIN, [entity0])
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
@@ -2367,7 +2384,7 @@ async def test_report_no_color_modes(
@pytest.mark.parametrize(
("color_mode", "supported_color_modes", "effect", "warning_expected"),
("color_mode", "supported_color_modes", "effect", "error_expected"),
[
(light.ColorMode.ONOFF, {light.ColorMode.ONOFF}, None, False),
# A light which supports brightness should not set its color mode to on_off
@@ -2397,7 +2414,7 @@ async def test_report_invalid_color_mode(
color_mode: str,
supported_color_modes: set[str],
effect: str | None,
warning_expected: bool,
error_expected: bool,
) -> None:
"""Test a light setting an invalid color mode."""
@@ -2411,9 +2428,13 @@ async def test_report_invalid_color_mode(
entity = MockLightEntityEntity()
platform = MockEntityPlatform(hass, domain="test", platform_name="test")
await platform.async_add_entities([entity])
entity._async_calculate_state()
expected_warning = f"set to unsupported color mode {color_mode}"
assert (expected_warning in caplog.text) is warning_expected
raised_error = ""
try:
entity._async_calculate_state()
except HomeAssistantError as err:
raised_error = str(err)
expected_error = f"set to unsupported color mode {color_mode}"
assert (expected_error in raised_error) is error_expected
@pytest.mark.parametrize(