diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 29c75a4fc22f..c27a81c6dc26 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -128,6 +128,7 @@ from .const import ( # noqa: F401 SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, MediaPlayerEntityFeature, + RepeatMode, ) from .errors import BrowseError @@ -410,7 +411,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: component.async_register_entity_service( SERVICE_REPEAT_SET, - {vol.Required(ATTR_MEDIA_REPEAT): vol.In(REPEAT_MODES)}, + {vol.Required(ATTR_MEDIA_REPEAT): vol.Coerce(RepeatMode)}, "async_set_repeat", [MediaPlayerEntityFeature.REPEAT_SET], ) @@ -801,11 +802,11 @@ class MediaPlayerEntity(Entity): """Enable/disable shuffle mode.""" await self.hass.async_add_executor_job(self.set_shuffle, shuffle) - def set_repeat(self, repeat: str) -> None: + def set_repeat(self, repeat: RepeatMode) -> None: """Set repeat mode.""" raise NotImplementedError() - async def async_set_repeat(self, repeat: str) -> None: + async def async_set_repeat(self, repeat: RepeatMode) -> None: """Set repeat mode.""" await self.hass.async_add_executor_job(self.set_repeat, repeat) diff --git a/homeassistant/components/media_player/browse_media.py b/homeassistant/components/media_player/browse_media.py index e3474eeb58ec..81ded203e75e 100644 --- a/homeassistant/components/media_player/browse_media.py +++ b/homeassistant/components/media_player/browse_media.py @@ -19,7 +19,7 @@ from homeassistant.helpers.network import ( is_hass_url, ) -from .const import CONTENT_AUTH_EXPIRY_TIME, MEDIA_CLASS_DIRECTORY +from .const import CONTENT_AUTH_EXPIRY_TIME, MediaClass, MediaType # Paths that we don't need to sign PATHS_WITHOUT_AUTH = ("/api/tts_proxy/",) @@ -92,14 +92,14 @@ class BrowseMedia: def __init__( self, *, - media_class: str, + media_class: MediaClass | str, media_content_id: str, - media_content_type: str, + media_content_type: MediaType | str, title: str, can_play: bool, can_expand: bool, children: Sequence[BrowseMedia] | None = None, - children_media_class: str | None = None, + children_media_class: MediaClass | str | None = None, thumbnail: str | None = None, not_shown: int = 0, ) -> None: @@ -115,7 +115,7 @@ class BrowseMedia: self.thumbnail = thumbnail self.not_shown = not_shown - def as_dict(self, *, parent: bool = True) -> dict: + def as_dict(self, *, parent: bool = True) -> dict[str, Any]: """Convert Media class to browse media dictionary.""" if self.children_media_class is None and self.children: self.calculate_children_class() @@ -147,7 +147,7 @@ class BrowseMedia: def calculate_children_class(self) -> None: """Count the children media classes and calculate the correct class.""" - self.children_media_class = MEDIA_CLASS_DIRECTORY + self.children_media_class = MediaClass.DIRECTORY assert self.children is not None proposed_class = self.children[0].media_class if all(child.media_class == proposed_class for child in self.children): diff --git a/homeassistant/components/media_player/const.py b/homeassistant/components/media_player/const.py index 4d534467ad65..2d3fa9c9b3e9 100644 --- a/homeassistant/components/media_player/const.py +++ b/homeassistant/components/media_player/const.py @@ -1,6 +1,8 @@ """Provides the constants needed for component.""" from enum import IntEnum +from homeassistant.backports.enum import StrEnum + # How long our auth signature on the content should be valid for CONTENT_AUTH_EXPIRY_TIME = 3600 * 24 @@ -38,6 +40,34 @@ ATTR_SOUND_MODE_LIST = "sound_mode_list" DOMAIN = "media_player" + +class MediaClass(StrEnum): + """Media class for media player entities.""" + + ALBUM = "album" + APP = "app" + ARTIST = "artist" + CHANNEL = "channel" + COMPOSER = "composer" + CONTRIBUTING_ARTIST = "contributing_artist" + DIRECTORY = "directory" + EPISODE = "episode" + GAME = "game" + GENRE = "genre" + IMAGE = "image" + MOVIE = "movie" + MUSIC = "music" + PLAYLIST = "playlist" + PODCAST = "podcast" + SEASON = "season" + TRACK = "track" + TV_SHOW = "tv_show" + URL = "url" + VIDEO = "video" + + +# These MEDIA_CLASS_* constants are deprecated as of Home Assistant 2022.10. +# Please use the MediaClass enum instead. MEDIA_CLASS_ALBUM = "album" MEDIA_CLASS_APP = "app" MEDIA_CLASS_ARTIST = "artist" @@ -59,6 +89,35 @@ MEDIA_CLASS_TV_SHOW = "tv_show" MEDIA_CLASS_URL = "url" MEDIA_CLASS_VIDEO = "video" + +class MediaType(StrEnum): + """Media type for media player entities.""" + + ALBUM = "album" + APP = "app" + APPS = "apps" + ARTIST = "artist" + CHANNEL = "channel" + CHANNELS = "channels" + COMPOSER = "composer" + CONTRIBUTING_ARTIST = "contributing_artist" + EPISODE = "episode" + GAME = "game" + GENRE = "genre" + IMAGE = "image" + MOVIE = "movie" + MUSIC = "music" + PLAYLIST = "playlist" + PODCAST = "podcast" + SEASON = "season" + TRACK = "track" + TVSHOW = "tvshow" + URL = "url" + VIDEO = "video" + + +# These MEDIA_TYPE_* constants are deprecated as of Home Assistant 2022.10. +# Please use the MediaType enum instead. MEDIA_TYPE_ALBUM = "album" MEDIA_TYPE_APP = "app" MEDIA_TYPE_APPS = "apps" @@ -88,6 +147,17 @@ SERVICE_SELECT_SOUND_MODE = "select_sound_mode" SERVICE_SELECT_SOURCE = "select_source" SERVICE_UNJOIN = "unjoin" + +class RepeatMode(StrEnum): + """Repeat mode for media player entities.""" + + ALL = "all" + OFF = "off" + ONE = "one" + + +# These REPEAT_MODE_* constants are deprecated as of Home Assistant 2022.10. +# Please use the RepeatMode enum instead. REPEAT_MODE_ALL = "all" REPEAT_MODE_OFF = "off" REPEAT_MODE_ONE = "one" diff --git a/pylint/plugins/hass_enforce_type_hints.py b/pylint/plugins/hass_enforce_type_hints.py index 289f461c2231..2418b97c1986 100644 --- a/pylint/plugins/hass_enforce_type_hints.py +++ b/pylint/plugins/hass_enforce_type_hints.py @@ -1741,7 +1741,7 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = { TypeHintMatch( function_name="set_repeat", arg_types={ - 1: "str", + 1: "RepeatMode", }, return_type=None, has_async_counterpart=True,