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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user