Migrate light entity to use contains for LightEntityFeature with deprecation warnings (#106622)

This commit is contained in:
J. Nick Koston 2023-12-28 15:45:06 -10:00 committed by GitHub
parent e6c6327463
commit e4a25825d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 17 deletions

View File

@ -345,11 +345,11 @@ def filter_turn_off_params(
light: LightEntity, params: dict[str, Any]
) -> dict[str, Any]:
"""Filter out params not used in turn off or not supported by the light."""
supported_features = light.supported_features
supported_features = light.supported_features_compat
if not supported_features & LightEntityFeature.FLASH:
if LightEntityFeature.FLASH not in supported_features:
params.pop(ATTR_FLASH, None)
if not supported_features & LightEntityFeature.TRANSITION:
if LightEntityFeature.TRANSITION not in supported_features:
params.pop(ATTR_TRANSITION, None)
return {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)}
@ -357,13 +357,13 @@ def filter_turn_off_params(
def filter_turn_on_params(light: LightEntity, params: dict[str, Any]) -> dict[str, Any]:
"""Filter out params not supported by the light."""
supported_features = light.supported_features
supported_features = light.supported_features_compat
if not supported_features & LightEntityFeature.EFFECT:
if LightEntityFeature.EFFECT not in supported_features:
params.pop(ATTR_EFFECT, None)
if not supported_features & LightEntityFeature.FLASH:
if LightEntityFeature.FLASH not in supported_features:
params.pop(ATTR_FLASH, None)
if not supported_features & LightEntityFeature.TRANSITION:
if LightEntityFeature.TRANSITION not in supported_features:
params.pop(ATTR_TRANSITION, None)
supported_color_modes = (
@ -989,7 +989,7 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def capability_attributes(self) -> dict[str, Any]:
"""Return capability attributes."""
data: dict[str, Any] = {}
supported_features = self.supported_features
supported_features = self.supported_features_compat
supported_color_modes = self._light_internal_supported_color_modes
if ColorMode.COLOR_TEMP in supported_color_modes:
@ -1007,7 +1007,7 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
data[ATTR_MAX_MIREDS] = color_util.color_temperature_kelvin_to_mired(
self.min_color_temp_kelvin
)
if supported_features & LightEntityFeature.EFFECT:
if LightEntityFeature.EFFECT in supported_features:
data[ATTR_EFFECT_LIST] = self.effect_list
data[ATTR_SUPPORTED_COLOR_MODES] = sorted(supported_color_modes)
@ -1061,8 +1061,9 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def state_attributes(self) -> dict[str, Any] | None:
"""Return state attributes."""
data: dict[str, Any] = {}
supported_features = self.supported_features
supported_features = self.supported_features_compat
supported_color_modes = self._light_internal_supported_color_modes
supported_features_value = supported_features.value
color_mode = self._light_internal_color_mode if self.is_on else None
if color_mode and color_mode not in supported_color_modes:
@ -1081,7 +1082,7 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
data[ATTR_BRIGHTNESS] = self.brightness
else:
data[ATTR_BRIGHTNESS] = None
elif supported_features & SUPPORT_BRIGHTNESS:
elif supported_features_value & SUPPORT_BRIGHTNESS:
# Backwards compatibility for ambiguous / incomplete states
# Add warning in 2021.6, remove in 2021.10
if self.is_on:
@ -1103,7 +1104,7 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
else:
data[ATTR_COLOR_TEMP_KELVIN] = None
data[ATTR_COLOR_TEMP] = None
elif supported_features & SUPPORT_COLOR_TEMP:
elif supported_features_value & SUPPORT_COLOR_TEMP:
# Backwards compatibility
# Add warning in 2021.6, remove in 2021.10
if self.is_on:
@ -1133,7 +1134,7 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if color_mode:
data.update(self._light_internal_convert_color(color_mode))
if supported_features & LightEntityFeature.EFFECT:
if LightEntityFeature.EFFECT in supported_features:
data[ATTR_EFFECT] = self.effect if self.is_on else None
return data
@ -1146,14 +1147,15 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
# Backwards compatibility for supported_color_modes added in 2021.4
# Add warning in 2021.6, remove in 2021.10
supported_features = self.supported_features
supported_features = self.supported_features_compat
supported_features_value = supported_features.value
supported_color_modes: set[ColorMode] = set()
if supported_features & SUPPORT_COLOR_TEMP:
if supported_features_value & SUPPORT_COLOR_TEMP:
supported_color_modes.add(ColorMode.COLOR_TEMP)
if supported_features & SUPPORT_COLOR:
if supported_features_value & SUPPORT_COLOR:
supported_color_modes.add(ColorMode.HS)
if supported_features & SUPPORT_BRIGHTNESS and not supported_color_modes:
if not supported_color_modes and supported_features_value & SUPPORT_BRIGHTNESS:
supported_color_modes = {ColorMode.BRIGHTNESS}
if not supported_color_modes:
@ -1170,3 +1172,34 @@ class LightEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
def supported_features(self) -> LightEntityFeature:
"""Flag supported features."""
return self._attr_supported_features
@property
def supported_features_compat(self) -> LightEntityFeature:
"""Return the supported features as LightEntityFeature.
Remove this compatibility shim in 2025.1 or later.
"""
features = self.supported_features
if type(features) is not int: # noqa: E721
return features
new_features = LightEntityFeature(features)
if self._deprecated_supported_features_reported is True:
return new_features
self._deprecated_supported_features_reported = True
report_issue = self._suggest_report_issue()
report_issue += (
" and reference "
"https://developers.home-assistant.io/blog/2023/12/28/support-feature-magic-numbers-deprecation"
)
_LOGGER.warning(
(
"Entity %s (%s) is using deprecated supported features"
" values which will be removed in HA Core 2025.1. Instead it should use"
" %s and color modes, please %s"
),
self.entity_id,
type(self),
repr(new_features),
report_issue,
)
return new_features

View File

@ -2589,3 +2589,24 @@ def test_filter_supported_color_modes() -> None:
# ColorMode.BRIGHTNESS has priority over ColorMode.ONOFF
supported = {light.ColorMode.ONOFF, light.ColorMode.BRIGHTNESS}
assert light.filter_supported_color_modes(supported) == {light.ColorMode.BRIGHTNESS}
def test_deprecated_supported_features_ints(caplog: pytest.LogCaptureFixture) -> None:
"""Test deprecated supported features ints."""
class MockLightEntityEntity(light.LightEntity):
@property
def supported_features(self) -> int:
"""Return supported features."""
return 1
entity = MockLightEntityEntity()
assert entity.supported_features_compat is light.LightEntityFeature(1)
assert "MockLightEntityEntity" in caplog.text
assert "is using deprecated supported features values" in caplog.text
assert "Instead it should use" in caplog.text
assert "LightEntityFeature" in caplog.text
assert "and color modes" in caplog.text
caplog.clear()
assert entity.supported_features_compat is light.LightEntityFeature(1)
assert "is using deprecated supported features values" not in caplog.text