Update pyheos to 0.9.0 (#134947)

Bump pyheos
pull/135080/head
Andrew Sayre 2025-01-08 02:36:02 -06:00 committed by GitHub
parent dc1928f3eb
commit 3fea4efb9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 87 additions and 68 deletions

View File

@ -275,11 +275,11 @@ class GroupManager:
player_id_to_entity_id_map = self.entity_id_map
for group in groups.values():
leader_entity_id = player_id_to_entity_id_map.get(group.leader.player_id)
leader_entity_id = player_id_to_entity_id_map.get(group.lead_player_id)
member_entity_ids = [
player_id_to_entity_id_map[member.player_id]
for member in group.members
if member.player_id in player_id_to_entity_id_map
player_id_to_entity_id_map[member]
for member in group.member_player_ids
if member in player_id_to_entity_id_map
]
# Make sure the group leader is always the first element
group_info = [leader_entity_id, *member_entity_ids]
@ -422,7 +422,7 @@ class SourceManager:
None,
)
if index is not None:
await player.play_favorite(index)
await player.play_preset_station(index)
return
input_source = next(
@ -434,7 +434,7 @@ class SourceManager:
None,
)
if input_source is not None:
await player.play_input_source(input_source)
await player.play_input_source(input_source.media_id)
return
_LOGGER.error("Unknown source: %s", source)
@ -447,7 +447,7 @@ class SourceManager:
(
input_source.name
for input_source in self.inputs
if input_source.input_name == now_playing_media.media_id
if input_source.media_id == now_playing_media.media_id
),
None,
)

View File

@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/heos",
"iot_class": "local_push",
"loggers": ["pyheos"],
"requirements": ["pyheos==0.8.0"],
"requirements": ["pyheos==0.9.0"],
"single_config_entry": true,
"ssdp": [
{

View File

@ -47,9 +47,9 @@ BASE_SUPPORTED_FEATURES = (
)
PLAY_STATE_TO_STATE = {
heos_const.PLAY_STATE_PLAY: MediaPlayerState.PLAYING,
heos_const.PLAY_STATE_STOP: MediaPlayerState.IDLE,
heos_const.PLAY_STATE_PAUSE: MediaPlayerState.PAUSED,
heos_const.PlayState.PLAY: MediaPlayerState.PLAYING,
heos_const.PlayState.STOP: MediaPlayerState.IDLE,
heos_const.PlayState.PAUSE: MediaPlayerState.PAUSED,
}
CONTROL_TO_SUPPORT = {
@ -61,11 +61,11 @@ CONTROL_TO_SUPPORT = {
}
HA_HEOS_ENQUEUE_MAP = {
None: heos_const.ADD_QUEUE_REPLACE_AND_PLAY,
MediaPlayerEnqueue.ADD: heos_const.ADD_QUEUE_ADD_TO_END,
MediaPlayerEnqueue.REPLACE: heos_const.ADD_QUEUE_REPLACE_AND_PLAY,
MediaPlayerEnqueue.NEXT: heos_const.ADD_QUEUE_PLAY_NEXT,
MediaPlayerEnqueue.PLAY: heos_const.ADD_QUEUE_PLAY_NOW,
None: heos_const.AddCriteriaType.REPLACE_AND_PLAY,
MediaPlayerEnqueue.ADD: heos_const.AddCriteriaType.ADD_TO_END,
MediaPlayerEnqueue.REPLACE: heos_const.AddCriteriaType.REPLACE_AND_PLAY,
MediaPlayerEnqueue.NEXT: heos_const.AddCriteriaType.PLAY_NEXT,
MediaPlayerEnqueue.PLAY: heos_const.AddCriteriaType.PLAY_NOW,
}
_LOGGER = logging.getLogger(__name__)
@ -268,7 +268,7 @@ class HeosMediaPlayer(MediaPlayerEntity):
)
if index is None:
raise ValueError(f"Invalid favorite '{media_id}'")
await self._player.play_favorite(index)
await self._player.play_preset_station(index)
return
raise ValueError(f"Unsupported media type '{media_type}'")

View File

@ -1977,7 +1977,7 @@ pygti==0.9.4
pyhaversion==22.8.0
# homeassistant.components.heos
pyheos==0.8.0
pyheos==0.9.0
# homeassistant.components.hive
pyhiveapi==0.5.16

View File

@ -1606,7 +1606,7 @@ pygti==0.9.4
pyhaversion==22.8.0
# homeassistant.components.heos
pyheos==0.8.0
pyheos==0.9.0
# homeassistant.components.hive
pyhiveapi==0.5.16

View File

@ -5,15 +5,7 @@ from __future__ import annotations
from collections.abc import Sequence
from unittest.mock import Mock, patch
from pyheos import (
Dispatcher,
Heos,
HeosGroup,
HeosPlayer,
HeosSource,
InputSource,
const,
)
from pyheos import Dispatcher, Heos, HeosGroup, HeosPlayer, MediaItem, const
import pytest
import pytest_asyncio
@ -124,12 +116,13 @@ def player_fixture(quick_selects):
player.version = "1.0.0"
player.is_muted = False
player.available = True
player.state = const.PLAY_STATE_STOP
player.state = const.PlayState.STOP
player.ip_address = f"127.0.0.{i}"
player.network = "wired"
player.shuffle = False
player.repeat = const.REPEAT_OFF
player.repeat = const.RepeatType.OFF
player.volume = 25
player.now_playing_media = Mock()
player.now_playing_media.supported_controls = const.CONTROLS_ALL
player.now_playing_media.album_id = 1
player.now_playing_media.queue_id = 1
@ -151,34 +144,52 @@ def player_fixture(quick_selects):
@pytest.fixture(name="group")
def group_fixture(players):
"""Create a HEOS group consisting of two players."""
group = Mock(HeosGroup)
group.leader = players[1]
group.members = [players[2]]
group.group_id = 999
group = HeosGroup(
name="Group", group_id=999, lead_player_id=1, member_player_ids=[2]
)
return {group.group_id: group}
@pytest.fixture(name="favorites")
def favorites_fixture() -> dict[int, HeosSource]:
def favorites_fixture() -> dict[int, MediaItem]:
"""Create favorites fixture."""
station = Mock(HeosSource)
station.type = const.TYPE_STATION
station.name = "Today's Hits Radio"
station.media_id = "123456789"
radio = Mock(HeosSource)
radio.type = const.TYPE_STATION
radio.name = "Classical MPR (Classical Music)"
radio.media_id = "s1234"
station = MediaItem(
source_id=const.MUSIC_SOURCE_PANDORA,
name="Today's Hits Radio",
media_id="123456789",
type=const.MediaType.STATION,
playable=True,
browsable=False,
image_url="",
heos=None,
)
radio = MediaItem(
source_id=const.MUSIC_SOURCE_TUNEIN,
name="Classical MPR (Classical Music)",
media_id="s1234",
type=const.MediaType.STATION,
playable=True,
browsable=False,
image_url="",
heos=None,
)
return {1: station, 2: radio}
@pytest.fixture(name="input_sources")
def input_sources_fixture() -> Sequence[InputSource]:
def input_sources_fixture() -> Sequence[MediaItem]:
"""Create a set of input sources for testing."""
source = Mock(InputSource)
source.player_id = 1
source.input_name = const.INPUT_AUX_IN_1
source.name = "HEOS Drive - Line In 1"
source = MediaItem(
source_id=1,
name="HEOS Drive - Line In 1",
media_id=const.INPUT_AUX_IN_1,
type=const.MediaType.STATION,
playable=True,
browsable=False,
image_url="",
heos=None,
)
return [source]
@ -240,11 +251,17 @@ def quick_selects_fixture() -> dict[int, str]:
@pytest.fixture(name="playlists")
def playlists_fixture() -> Sequence[HeosSource]:
def playlists_fixture() -> Sequence[MediaItem]:
"""Create favorites fixture."""
playlist = Mock(HeosSource)
playlist.type = const.TYPE_PLAYLIST
playlist.name = "Awesome Music"
playlist = MediaItem(
source_id=const.MUSIC_SOURCE_PLAYLISTS,
name="Awesome Music",
type=const.MediaType.PLAYLIST,
playable=True,
browsable=True,
image_url="",
heos=None,
)
return [playlist]

View File

@ -115,7 +115,7 @@ async def test_updates_from_signals(
player = controller.players[1]
# Test player does not update for other players
player.state = const.PLAY_STATE_PLAY
player.state = const.PlayState.PLAY
player.heos.dispatcher.send(
const.SIGNAL_PLAYER_EVENT, 2, const.EVENT_PLAYER_STATE_CHANGED
)
@ -124,7 +124,7 @@ async def test_updates_from_signals(
assert state.state == STATE_IDLE
# Test player_update standard events
player.state = const.PLAY_STATE_PLAY
player.state = const.PlayState.PLAY
player.heos.dispatcher.send(
const.SIGNAL_PLAYER_EVENT, player.player_id, const.EVENT_PLAYER_STATE_CHANGED
)
@ -241,7 +241,7 @@ async def test_updates_from_players_changed(
async_dispatcher_connect(hass, SIGNAL_HEOS_UPDATED, set_signal)
assert hass.states.get("media_player.test_player").state == STATE_IDLE
player.state = const.PLAY_STATE_PLAY
player.state = const.PlayState.PLAY
player.heos.dispatcher.send(
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_PLAYERS_CHANGED, change_data
)
@ -551,7 +551,7 @@ async def test_select_favorite(
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
blocking=True,
)
player.play_favorite.assert_called_once_with(1)
player.play_preset_station.assert_called_once_with(1)
# Test state is matched by station name
player.now_playing_media.station = favorite.name
player.heos.dispatcher.send(
@ -576,7 +576,7 @@ async def test_select_radio_favorite(
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
blocking=True,
)
player.play_favorite.assert_called_once_with(2)
player.play_preset_station.assert_called_once_with(2)
# Test state is matched by album id
player.now_playing_media.station = "Classical"
player.now_playing_media.album_id = favorite.media_id
@ -601,14 +601,14 @@ async def test_select_radio_favorite_command_error(
player = controller.players[1]
# Test set radio preset
favorite = favorites[2]
player.play_favorite.side_effect = CommandFailedError(None, "Failure", 1)
player.play_preset_station.side_effect = CommandFailedError(None, "Failure", 1)
await hass.services.async_call(
MEDIA_PLAYER_DOMAIN,
SERVICE_SELECT_SOURCE,
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
blocking=True,
)
player.play_favorite.assert_called_once_with(2)
player.play_preset_station.assert_called_once_with(2)
assert "Unable to select source: Failure (1)" in caplog.text
@ -629,7 +629,7 @@ async def test_select_input_source(
},
blocking=True,
)
player.play_input_source.assert_called_once_with(input_source)
player.play_input_source.assert_called_once_with(input_source.media_id)
# Test state is matched by media id
player.now_playing_media.source_id = const.MUSIC_SOURCE_AUX_INPUT
player.now_playing_media.media_id = const.INPUT_AUX_IN_1
@ -681,7 +681,7 @@ async def test_select_input_command_error(
},
blocking=True,
)
player.play_input_source.assert_called_once_with(input_source)
player.play_input_source.assert_called_once_with(input_source.media_id)
assert "Unable to select source: Failure (1)" in caplog.text
@ -831,7 +831,7 @@ async def test_play_media_playlist(
blocking=True,
)
player.add_to_queue.assert_called_once_with(
playlist, const.ADD_QUEUE_REPLACE_AND_PLAY
playlist, const.AddCriteriaType.REPLACE_AND_PLAY
)
# Play with enqueuing
player.add_to_queue.reset_mock()
@ -846,7 +846,9 @@ async def test_play_media_playlist(
},
blocking=True,
)
player.add_to_queue.assert_called_once_with(playlist, const.ADD_QUEUE_ADD_TO_END)
player.add_to_queue.assert_called_once_with(
playlist, const.AddCriteriaType.ADD_TO_END
)
# Invalid name
player.add_to_queue.reset_mock()
await hass.services.async_call(
@ -888,9 +890,9 @@ async def test_play_media_favorite(
},
blocking=True,
)
player.play_favorite.assert_called_once_with(index)
player.play_preset_station.assert_called_once_with(index)
# Play by name
player.play_favorite.reset_mock()
player.play_preset_station.reset_mock()
await hass.services.async_call(
MEDIA_PLAYER_DOMAIN,
SERVICE_PLAY_MEDIA,
@ -901,9 +903,9 @@ async def test_play_media_favorite(
},
blocking=True,
)
player.play_favorite.assert_called_once_with(index)
player.play_preset_station.assert_called_once_with(index)
# Invalid name
player.play_favorite.reset_mock()
player.play_preset_station.reset_mock()
await hass.services.async_call(
MEDIA_PLAYER_DOMAIN,
SERVICE_PLAY_MEDIA,
@ -914,7 +916,7 @@ async def test_play_media_favorite(
},
blocking=True,
)
assert player.play_favorite.call_count == 0
assert player.play_preset_station.call_count == 0
assert "Unable to play media: Invalid favorite 'Invalid'" in caplog.text