diff --git a/homeassistant/components/spotify/__init__.py b/homeassistant/components/spotify/__init__.py index 8d5183a459d..9bf43609855 100644 --- a/homeassistant/components/spotify/__init__.py +++ b/homeassistant/components/spotify/__init__.py @@ -30,6 +30,7 @@ from .util import ( PLATFORMS = [Platform.MEDIA_PLAYER] +SpotifyConfigEntry = ConfigEntry["HomeAssistantSpotifyData"] __all__ = [ "async_browse_media", @@ -50,7 +51,7 @@ class HomeAssistantSpotifyData: session: OAuth2Session -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_setup_entry(hass: HomeAssistant, entry: SpotifyConfigEntry) -> bool: """Set up Spotify from a config entry.""" implementation = await async_get_config_entry_implementation(hass, entry) session = OAuth2Session(hass, entry, implementation) @@ -100,8 +101,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ) await device_coordinator.async_config_entry_first_refresh() - hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = HomeAssistantSpotifyData( + entry.runtime_data = HomeAssistantSpotifyData( client=spotify, current_user=current_user, devices=device_coordinator, @@ -117,6 +117,4 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload Spotify config entry.""" - if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): - del hass.data[DOMAIN][entry.entry_id] - return unload_ok + return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) diff --git a/homeassistant/components/spotify/browse_media.py b/homeassistant/components/spotify/browse_media.py index cc8f57be1bb..a1d3d9c804a 100644 --- a/homeassistant/components/spotify/browse_media.py +++ b/homeassistant/components/spotify/browse_media.py @@ -5,7 +5,7 @@ from __future__ import annotations from enum import StrEnum from functools import partial import logging -from typing import Any +from typing import TYPE_CHECKING, Any from spotipy import Spotify import yarl @@ -22,6 +22,9 @@ from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session from .const import DOMAIN, MEDIA_PLAYER_PREFIX, MEDIA_TYPE_SHOW, PLAYABLE_MEDIA_TYPES from .util import fetch_image_url +if TYPE_CHECKING: + from . import HomeAssistantSpotifyData + BROWSE_LIMIT = 48 @@ -140,21 +143,21 @@ async def async_browse_media( # Check if caller is requesting the root nodes if media_content_type is None and media_content_id is None: - children = [] - for config_entry_id in hass.data[DOMAIN]: - config_entry = hass.config_entries.async_get_entry(config_entry_id) - assert config_entry is not None - children.append( - BrowseMedia( - title=config_entry.title, - media_class=MediaClass.APP, - media_content_id=f"{MEDIA_PLAYER_PREFIX}{config_entry_id}", - media_content_type=f"{MEDIA_PLAYER_PREFIX}library", - thumbnail="https://brands.home-assistant.io/_/spotify/logo.png", - can_play=False, - can_expand=True, - ) + config_entries = hass.config_entries.async_entries( + DOMAIN, include_disabled=False, include_ignore=False + ) + children = [ + BrowseMedia( + title=config_entry.title, + media_class=MediaClass.APP, + media_content_id=f"{MEDIA_PLAYER_PREFIX}{config_entry.entry_id}", + media_content_type=f"{MEDIA_PLAYER_PREFIX}library", + thumbnail="https://brands.home-assistant.io/_/spotify/logo.png", + can_play=False, + can_expand=True, ) + for config_entry in config_entries + ] return BrowseMedia( title="Spotify", media_class=MediaClass.APP, @@ -171,9 +174,15 @@ async def async_browse_media( # Check for config entry specifier, and extract Spotify URI parsed_url = yarl.URL(media_content_id) - if (info := hass.data[DOMAIN].get(parsed_url.host)) is None: + + if ( + parsed_url.host is None + or (entry := hass.config_entries.async_get_entry(parsed_url.host)) is None + or not isinstance(entry.runtime_data, HomeAssistantSpotifyData) + ): raise BrowseError("Invalid Spotify account specified") media_content_id = parsed_url.name + info = entry.runtime_data result = await async_browse_media_internal( hass, diff --git a/homeassistant/components/spotify/media_player.py b/homeassistant/components/spotify/media_player.py index fc7a084939a..fe9614374f7 100644 --- a/homeassistant/components/spotify/media_player.py +++ b/homeassistant/components/spotify/media_player.py @@ -22,7 +22,6 @@ from homeassistant.components.media_player import ( MediaType, RepeatMode, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_ID from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError @@ -30,7 +29,7 @@ from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.util.dt import utcnow -from . import HomeAssistantSpotifyData +from . import HomeAssistantSpotifyData, SpotifyConfigEntry from .browse_media import async_browse_media_internal from .const import DOMAIN, MEDIA_PLAYER_PREFIX, PLAYABLE_MEDIA_TYPES, SPOTIFY_SCOPES from .util import fetch_image_url @@ -70,12 +69,12 @@ SPOTIFY_DJ_PLAYLIST = {"uri": "spotify:playlist:37i9dQZF1EYkqdzj48dyYq", "name": async def async_setup_entry( hass: HomeAssistant, - entry: ConfigEntry, + entry: SpotifyConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up Spotify based on a config entry.""" spotify = SpotifyMediaPlayer( - hass.data[DOMAIN][entry.entry_id], + entry.runtime_data, entry.data[CONF_ID], entry.title, )