mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Remove deprecated supported features warning in MediaPlayer (#132365)
This commit is contained in:
parent
772b047d44
commit
f2500e5a32
@ -773,19 +773,6 @@ class MediaPlayerEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
"""Flag media player features that are supported."""
|
"""Flag media player features that are supported."""
|
||||||
return self._attr_supported_features
|
return self._attr_supported_features
|
||||||
|
|
||||||
@property
|
|
||||||
def supported_features_compat(self) -> MediaPlayerEntityFeature:
|
|
||||||
"""Return the supported features as MediaPlayerEntityFeature.
|
|
||||||
|
|
||||||
Remove this compatibility shim in 2025.1 or later.
|
|
||||||
"""
|
|
||||||
features = self.supported_features
|
|
||||||
if type(features) is int: # noqa: E721
|
|
||||||
new_features = MediaPlayerEntityFeature(features)
|
|
||||||
self._report_deprecated_supported_features_values(new_features)
|
|
||||||
return new_features
|
|
||||||
return features
|
|
||||||
|
|
||||||
def turn_on(self) -> None:
|
def turn_on(self) -> None:
|
||||||
"""Turn the media player on."""
|
"""Turn the media player on."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -925,87 +912,85 @@ class MediaPlayerEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
@property
|
@property
|
||||||
def support_play(self) -> bool:
|
def support_play(self) -> bool:
|
||||||
"""Boolean if play is supported."""
|
"""Boolean if play is supported."""
|
||||||
return MediaPlayerEntityFeature.PLAY in self.supported_features_compat
|
return MediaPlayerEntityFeature.PLAY in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_pause(self) -> bool:
|
def support_pause(self) -> bool:
|
||||||
"""Boolean if pause is supported."""
|
"""Boolean if pause is supported."""
|
||||||
return MediaPlayerEntityFeature.PAUSE in self.supported_features_compat
|
return MediaPlayerEntityFeature.PAUSE in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_stop(self) -> bool:
|
def support_stop(self) -> bool:
|
||||||
"""Boolean if stop is supported."""
|
"""Boolean if stop is supported."""
|
||||||
return MediaPlayerEntityFeature.STOP in self.supported_features_compat
|
return MediaPlayerEntityFeature.STOP in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_seek(self) -> bool:
|
def support_seek(self) -> bool:
|
||||||
"""Boolean if seek is supported."""
|
"""Boolean if seek is supported."""
|
||||||
return MediaPlayerEntityFeature.SEEK in self.supported_features_compat
|
return MediaPlayerEntityFeature.SEEK in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_volume_set(self) -> bool:
|
def support_volume_set(self) -> bool:
|
||||||
"""Boolean if setting volume is supported."""
|
"""Boolean if setting volume is supported."""
|
||||||
return MediaPlayerEntityFeature.VOLUME_SET in self.supported_features_compat
|
return MediaPlayerEntityFeature.VOLUME_SET in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_volume_mute(self) -> bool:
|
def support_volume_mute(self) -> bool:
|
||||||
"""Boolean if muting volume is supported."""
|
"""Boolean if muting volume is supported."""
|
||||||
return MediaPlayerEntityFeature.VOLUME_MUTE in self.supported_features_compat
|
return MediaPlayerEntityFeature.VOLUME_MUTE in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_previous_track(self) -> bool:
|
def support_previous_track(self) -> bool:
|
||||||
"""Boolean if previous track command supported."""
|
"""Boolean if previous track command supported."""
|
||||||
return MediaPlayerEntityFeature.PREVIOUS_TRACK in self.supported_features_compat
|
return MediaPlayerEntityFeature.PREVIOUS_TRACK in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_next_track(self) -> bool:
|
def support_next_track(self) -> bool:
|
||||||
"""Boolean if next track command supported."""
|
"""Boolean if next track command supported."""
|
||||||
return MediaPlayerEntityFeature.NEXT_TRACK in self.supported_features_compat
|
return MediaPlayerEntityFeature.NEXT_TRACK in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_play_media(self) -> bool:
|
def support_play_media(self) -> bool:
|
||||||
"""Boolean if play media command supported."""
|
"""Boolean if play media command supported."""
|
||||||
return MediaPlayerEntityFeature.PLAY_MEDIA in self.supported_features_compat
|
return MediaPlayerEntityFeature.PLAY_MEDIA in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_select_source(self) -> bool:
|
def support_select_source(self) -> bool:
|
||||||
"""Boolean if select source command supported."""
|
"""Boolean if select source command supported."""
|
||||||
return MediaPlayerEntityFeature.SELECT_SOURCE in self.supported_features_compat
|
return MediaPlayerEntityFeature.SELECT_SOURCE in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_select_sound_mode(self) -> bool:
|
def support_select_sound_mode(self) -> bool:
|
||||||
"""Boolean if select sound mode command supported."""
|
"""Boolean if select sound mode command supported."""
|
||||||
return (
|
return MediaPlayerEntityFeature.SELECT_SOUND_MODE in self.supported_features
|
||||||
MediaPlayerEntityFeature.SELECT_SOUND_MODE in self.supported_features_compat
|
|
||||||
)
|
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_clear_playlist(self) -> bool:
|
def support_clear_playlist(self) -> bool:
|
||||||
"""Boolean if clear playlist command supported."""
|
"""Boolean if clear playlist command supported."""
|
||||||
return MediaPlayerEntityFeature.CLEAR_PLAYLIST in self.supported_features_compat
|
return MediaPlayerEntityFeature.CLEAR_PLAYLIST in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_shuffle_set(self) -> bool:
|
def support_shuffle_set(self) -> bool:
|
||||||
"""Boolean if shuffle is supported."""
|
"""Boolean if shuffle is supported."""
|
||||||
return MediaPlayerEntityFeature.SHUFFLE_SET in self.supported_features_compat
|
return MediaPlayerEntityFeature.SHUFFLE_SET in self.supported_features
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@property
|
@property
|
||||||
def support_grouping(self) -> bool:
|
def support_grouping(self) -> bool:
|
||||||
"""Boolean if player grouping is supported."""
|
"""Boolean if player grouping is supported."""
|
||||||
return MediaPlayerEntityFeature.GROUPING in self.supported_features_compat
|
return MediaPlayerEntityFeature.GROUPING in self.supported_features
|
||||||
|
|
||||||
async def async_toggle(self) -> None:
|
async def async_toggle(self) -> None:
|
||||||
"""Toggle the power on the media player."""
|
"""Toggle the power on the media player."""
|
||||||
@ -1034,7 +1019,7 @@ class MediaPlayerEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
if (
|
if (
|
||||||
self.volume_level is not None
|
self.volume_level is not None
|
||||||
and self.volume_level < 1
|
and self.volume_level < 1
|
||||||
and MediaPlayerEntityFeature.VOLUME_SET in self.supported_features_compat
|
and MediaPlayerEntityFeature.VOLUME_SET in self.supported_features
|
||||||
):
|
):
|
||||||
await self.async_set_volume_level(
|
await self.async_set_volume_level(
|
||||||
min(1, self.volume_level + self.volume_step)
|
min(1, self.volume_level + self.volume_step)
|
||||||
@ -1052,7 +1037,7 @@ class MediaPlayerEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
if (
|
if (
|
||||||
self.volume_level is not None
|
self.volume_level is not None
|
||||||
and self.volume_level > 0
|
and self.volume_level > 0
|
||||||
and MediaPlayerEntityFeature.VOLUME_SET in self.supported_features_compat
|
and MediaPlayerEntityFeature.VOLUME_SET in self.supported_features
|
||||||
):
|
):
|
||||||
await self.async_set_volume_level(
|
await self.async_set_volume_level(
|
||||||
max(0, self.volume_level - self.volume_step)
|
max(0, self.volume_level - self.volume_step)
|
||||||
@ -1095,7 +1080,7 @@ class MediaPlayerEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
def capability_attributes(self) -> dict[str, Any]:
|
def capability_attributes(self) -> dict[str, Any]:
|
||||||
"""Return capability attributes."""
|
"""Return capability attributes."""
|
||||||
data: dict[str, Any] = {}
|
data: dict[str, Any] = {}
|
||||||
supported_features = self.supported_features_compat
|
supported_features = self.supported_features
|
||||||
|
|
||||||
if (
|
if (
|
||||||
source_list := self.source_list
|
source_list := self.source_list
|
||||||
@ -1301,7 +1286,7 @@ async def websocket_browse_media(
|
|||||||
connection.send_error(msg["id"], "entity_not_found", "Entity not found")
|
connection.send_error(msg["id"], "entity_not_found", "Entity not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
if MediaPlayerEntityFeature.BROWSE_MEDIA not in player.supported_features_compat:
|
if MediaPlayerEntityFeature.BROWSE_MEDIA not in player.supported_features:
|
||||||
connection.send_message(
|
connection.send_message(
|
||||||
websocket_api.error_message(
|
websocket_api.error_message(
|
||||||
msg["id"], ERR_NOT_SUPPORTED, "Player does not support browsing media"
|
msg["id"], ERR_NOT_SUPPORTED, "Player does not support browsing media"
|
||||||
|
@ -7,7 +7,7 @@ import asyncio
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
from collections.abc import Callable, Coroutine, Iterable, Mapping
|
from collections.abc import Callable, Coroutine, Iterable, Mapping
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from enum import Enum, IntFlag, auto
|
from enum import Enum, auto
|
||||||
import functools as ft
|
import functools as ft
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
@ -1639,31 +1639,6 @@ class Entity(
|
|||||||
self.hass, integration_domain=platform_name, module=type(self).__module__
|
self.hass, integration_domain=platform_name, module=type(self).__module__
|
||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
|
||||||
def _report_deprecated_supported_features_values(
|
|
||||||
self, replacement: IntFlag
|
|
||||||
) -> None:
|
|
||||||
"""Report deprecated supported features values."""
|
|
||||||
if self._deprecated_supported_features_reported is True:
|
|
||||||
return
|
|
||||||
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, please %s"
|
|
||||||
),
|
|
||||||
self.entity_id,
|
|
||||||
type(self),
|
|
||||||
repr(replacement),
|
|
||||||
report_issue,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ToggleEntityDescription(EntityDescription, frozen_or_thawed=True):
|
class ToggleEntityDescription(EntityDescription, frozen_or_thawed=True):
|
||||||
"""A class that describes toggle entities."""
|
"""A class that describes toggle entities."""
|
||||||
|
@ -129,7 +129,7 @@ def test_support_properties(property_suffix: str) -> None:
|
|||||||
entity3 = MediaPlayerEntity()
|
entity3 = MediaPlayerEntity()
|
||||||
entity3._attr_supported_features = feature
|
entity3._attr_supported_features = feature
|
||||||
entity4 = MediaPlayerEntity()
|
entity4 = MediaPlayerEntity()
|
||||||
entity4._attr_supported_features = all_features - feature
|
entity4._attr_supported_features = all_features & ~feature
|
||||||
|
|
||||||
assert getattr(entity1, f"support_{property_suffix}") is False
|
assert getattr(entity1, f"support_{property_suffix}") is False
|
||||||
assert getattr(entity2, f"support_{property_suffix}") is True
|
assert getattr(entity2, f"support_{property_suffix}") is True
|
||||||
@ -447,23 +447,3 @@ async def test_get_async_get_browse_image_quoting(
|
|||||||
url = player.get_browse_image_url("album", media_content_id)
|
url = player.get_browse_image_url("album", media_content_id)
|
||||||
await client.get(url)
|
await client.get(url)
|
||||||
mock_browse_image.assert_called_with("album", media_content_id, None)
|
mock_browse_image.assert_called_with("album", media_content_id, None)
|
||||||
|
|
||||||
|
|
||||||
def test_deprecated_supported_features_ints(caplog: pytest.LogCaptureFixture) -> None:
|
|
||||||
"""Test deprecated supported features ints."""
|
|
||||||
|
|
||||||
class MockMediaPlayerEntity(MediaPlayerEntity):
|
|
||||||
@property
|
|
||||||
def supported_features(self) -> int:
|
|
||||||
"""Return supported features."""
|
|
||||||
return 1
|
|
||||||
|
|
||||||
entity = MockMediaPlayerEntity()
|
|
||||||
assert entity.supported_features_compat is MediaPlayerEntityFeature(1)
|
|
||||||
assert "MockMediaPlayerEntity" in caplog.text
|
|
||||||
assert "is using deprecated supported features values" in caplog.text
|
|
||||||
assert "Instead it should use" in caplog.text
|
|
||||||
assert "MediaPlayerEntityFeature.PAUSE" in caplog.text
|
|
||||||
caplog.clear()
|
|
||||||
assert entity.supported_features_compat is MediaPlayerEntityFeature(1)
|
|
||||||
assert "is using deprecated supported features values" not in caplog.text
|
|
||||||
|
@ -4,7 +4,6 @@ import asyncio
|
|||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from enum import IntFlag
|
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -2486,31 +2485,6 @@ async def test_cached_entity_property_override(hass: HomeAssistant) -> None:
|
|||||||
return "🤡"
|
return "🤡"
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_report_deprecated_supported_features_values(
|
|
||||||
caplog: pytest.LogCaptureFixture,
|
|
||||||
) -> None:
|
|
||||||
"""Test reporting deprecated supported feature values only happens once."""
|
|
||||||
ent = entity.Entity()
|
|
||||||
|
|
||||||
class MockEntityFeatures(IntFlag):
|
|
||||||
VALUE1 = 1
|
|
||||||
VALUE2 = 2
|
|
||||||
|
|
||||||
ent._report_deprecated_supported_features_values(MockEntityFeatures(2))
|
|
||||||
assert (
|
|
||||||
"is using deprecated supported features values which will be removed"
|
|
||||||
in caplog.text
|
|
||||||
)
|
|
||||||
assert "MockEntityFeatures.VALUE2" in caplog.text
|
|
||||||
|
|
||||||
caplog.clear()
|
|
||||||
ent._report_deprecated_supported_features_values(MockEntityFeatures(2))
|
|
||||||
assert (
|
|
||||||
"is using deprecated supported features values which will be removed"
|
|
||||||
not in caplog.text
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_remove_entity_registry(
|
async def test_remove_entity_registry(
|
||||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user