Update pyheos to 0.6.0 (#26191)
This commit is contained in:
parent
afab0a9568
commit
677995a05a
11 changed files with 66 additions and 92 deletions
|
@ -4,7 +4,7 @@ from datetime import timedelta
|
|||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from pyheos import CommandError, Heos, const as heos_const
|
||||
from pyheos import Heos, HeosError, const as heos_const
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.media_player.const import DOMAIN as MEDIA_PLAYER_DOMAIN
|
||||
|
@ -68,7 +68,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||
try:
|
||||
await controller.connect(auto_reconnect=True)
|
||||
# Auto reconnect only operates if initial connection was successful.
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) as error:
|
||||
except HeosError as error:
|
||||
await controller.disconnect()
|
||||
_LOGGER.debug("Unable to connect to controller %s: %s", host, error)
|
||||
raise ConfigEntryNotReady
|
||||
|
@ -93,13 +93,9 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||
host,
|
||||
)
|
||||
inputs = await controller.get_input_sources()
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) as error:
|
||||
except HeosError as error:
|
||||
await controller.disconnect()
|
||||
_LOGGER.debug(
|
||||
"Unable to retrieve players and sources: %s",
|
||||
error,
|
||||
exc_info=isinstance(error, CommandError),
|
||||
)
|
||||
_LOGGER.debug("Unable to retrieve players and sources: %s", error)
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
controller_manager = ControllerManager(hass, controller)
|
||||
|
@ -187,7 +183,7 @@ class ControllerManager:
|
|||
# Retrieve latest players and refresh status
|
||||
data = await self.controller.load_players()
|
||||
self.update_ids(data[heos_const.DATA_MAPPED_IDS])
|
||||
except (CommandError, asyncio.TimeoutError, ConnectionError) as ex:
|
||||
except HeosError as ex:
|
||||
_LOGGER.error("Unable to refresh players: %s", ex)
|
||||
# Update players
|
||||
self._hass.helpers.dispatcher.async_dispatcher_send(SIGNAL_HEOS_UPDATED)
|
||||
|
@ -312,21 +308,15 @@ class SourceManager:
|
|||
favorites = await controller.get_favorites()
|
||||
inputs = await controller.get_input_sources()
|
||||
return favorites, inputs
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) as error:
|
||||
except HeosError as error:
|
||||
if retry_attempts < self.max_retry_attempts:
|
||||
retry_attempts += 1
|
||||
_LOGGER.debug(
|
||||
"Error retrieving sources and will " "retry: %s",
|
||||
error,
|
||||
exc_info=isinstance(error, CommandError),
|
||||
"Error retrieving sources and will " "retry: %s", error
|
||||
)
|
||||
await asyncio.sleep(self.retry_delay)
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Unable to update sources: %s",
|
||||
error,
|
||||
exc_info=isinstance(error, CommandError),
|
||||
)
|
||||
_LOGGER.error("Unable to update sources: %s", error)
|
||||
return
|
||||
|
||||
async def update_sources(event, data=None):
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
"""Config flow to configure Heos."""
|
||||
import asyncio
|
||||
|
||||
from pyheos import Heos
|
||||
from pyheos import Heos, HeosError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -59,7 +57,7 @@ class HeosFlowHandler(config_entries.ConfigFlow):
|
|||
await heos.connect()
|
||||
self.hass.data.pop(DATA_DISCOVERED_HOSTS)
|
||||
return await self.async_step_import({CONF_HOST: host})
|
||||
except (asyncio.TimeoutError, ConnectionError):
|
||||
except HeosError:
|
||||
errors[CONF_HOST] = "connection_failure"
|
||||
finally:
|
||||
await heos.disconnect()
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/components/heos",
|
||||
"requirements": [
|
||||
"pyheos==0.5.2"
|
||||
"pyheos==0.6.0"
|
||||
],
|
||||
"ssdp": {
|
||||
"st": [
|
||||
|
@ -15,4 +15,4 @@
|
|||
"codeowners": [
|
||||
"@andrewsayre"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
"""Denon HEOS Media Player."""
|
||||
import asyncio
|
||||
from functools import reduce, wraps
|
||||
import logging
|
||||
from operator import ior
|
||||
from typing import Sequence
|
||||
|
||||
from pyheos import CommandError, const as heos_const
|
||||
from pyheos import HeosError, const as heos_const
|
||||
|
||||
from homeassistant.components.media_player import MediaPlayerDevice
|
||||
from homeassistant.components.media_player.const import (
|
||||
|
@ -83,12 +82,7 @@ def log_command_error(command: str):
|
|||
async def wrapper(*args, **kwargs):
|
||||
try:
|
||||
await func(*args, **kwargs)
|
||||
except (
|
||||
CommandError,
|
||||
asyncio.TimeoutError,
|
||||
ConnectionError,
|
||||
ValueError,
|
||||
) as ex:
|
||||
except (HeosError, ValueError) as ex:
|
||||
_LOGGER.error("Unable to %s: %s", command, ex)
|
||||
|
||||
return wrapper
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
"""Services for the HEOS integration."""
|
||||
import asyncio
|
||||
import functools
|
||||
import logging
|
||||
|
||||
from pyheos import CommandError, Heos, const
|
||||
from pyheos import CommandFailedError, Heos, HeosError, const
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
@ -57,9 +56,9 @@ async def _sign_in_handler(controller, service):
|
|||
password = service.data[ATTR_PASSWORD]
|
||||
try:
|
||||
await controller.sign_in(username, password)
|
||||
except CommandError as err:
|
||||
except CommandFailedError as err:
|
||||
_LOGGER.error("Sign in failed: %s", err)
|
||||
except (asyncio.TimeoutError, ConnectionError) as err:
|
||||
except HeosError as err:
|
||||
_LOGGER.error("Unable to sign in: %s", err)
|
||||
|
||||
|
||||
|
@ -70,5 +69,5 @@ async def _sign_out_handler(controller, service):
|
|||
return
|
||||
try:
|
||||
await controller.sign_out()
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) as err:
|
||||
except HeosError as err:
|
||||
_LOGGER.error("Unable to sign out: %s", err)
|
||||
|
|
|
@ -1186,7 +1186,7 @@ pygtt==1.1.2
|
|||
pyhaversion==3.0.2
|
||||
|
||||
# homeassistant.components.heos
|
||||
pyheos==0.5.2
|
||||
pyheos==0.6.0
|
||||
|
||||
# homeassistant.components.hikvision
|
||||
pyhik==0.2.3
|
||||
|
|
|
@ -277,7 +277,7 @@ pydeconz==62
|
|||
pydispatcher==2.0.5
|
||||
|
||||
# homeassistant.components.heos
|
||||
pyheos==0.5.2
|
||||
pyheos==0.6.0
|
||||
|
||||
# homeassistant.components.homematic
|
||||
pyhomematic==0.1.60
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""Tests for the Heos config flow module."""
|
||||
import asyncio
|
||||
from pyheos import HeosError
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.heos.config_flow import HeosFlowHandler
|
||||
|
@ -31,18 +31,15 @@ async def test_cannot_connect_shows_error_form(hass, controller):
|
|||
"""Test form is shown with error when cannot connect."""
|
||||
flow = HeosFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
errors = [ConnectionError, asyncio.TimeoutError]
|
||||
for error in errors:
|
||||
controller.connect.side_effect = error
|
||||
result = await flow.async_step_user({CONF_HOST: "127.0.0.1"})
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"][CONF_HOST] == "connection_failure"
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
controller.connect.side_effect = HeosError()
|
||||
result = await flow.async_step_user({CONF_HOST: "127.0.0.1"})
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"][CONF_HOST] == "connection_failure"
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
|
||||
|
||||
async def test_create_entry_when_host_valid(hass, controller):
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import asyncio
|
||||
|
||||
from asynctest import Mock, patch
|
||||
from pyheos import CommandError, const
|
||||
from pyheos import CommandFailedError, HeosError, const
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.heos import (
|
||||
|
@ -117,31 +117,27 @@ async def test_async_setup_entry_not_signed_in_loads_platforms(
|
|||
async def test_async_setup_entry_connect_failure(hass, config_entry, controller):
|
||||
"""Connection failure raises ConfigEntryNotReady."""
|
||||
config_entry.add_to_hass(hass)
|
||||
errors = [ConnectionError, asyncio.TimeoutError]
|
||||
for error in errors:
|
||||
controller.connect.side_effect = error
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
controller.connect.side_effect = HeosError()
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
|
||||
|
||||
async def test_async_setup_entry_player_failure(hass, config_entry, controller):
|
||||
"""Failure to retrieve players/sources raises ConfigEntryNotReady."""
|
||||
config_entry.add_to_hass(hass)
|
||||
errors = [ConnectionError, asyncio.TimeoutError]
|
||||
for error in errors:
|
||||
controller.get_players.side_effect = error
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
controller.get_players.side_effect = HeosError()
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.disconnect.call_count == 1
|
||||
controller.connect.reset_mock()
|
||||
controller.disconnect.reset_mock()
|
||||
|
||||
|
||||
async def test_unload_entry(hass, config_entry, controller):
|
||||
|
@ -167,7 +163,7 @@ async def test_update_sources_retry(hass, config_entry, config, controller, capl
|
|||
source_manager = hass.data[DOMAIN][DATA_SOURCE_MANAGER]
|
||||
source_manager.retry_delay = 0
|
||||
source_manager.max_retry_attempts = 1
|
||||
controller.get_favorites.side_effect = CommandError("Test", "test", 0)
|
||||
controller.get_favorites.side_effect = CommandFailedError("Test", "test", 0)
|
||||
controller.dispatcher.send(
|
||||
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_SOURCES_CHANGED, {}
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Tests for the Heos Media Player platform."""
|
||||
import asyncio
|
||||
|
||||
from pyheos import CommandError, const
|
||||
from pyheos import CommandFailedError, const
|
||||
|
||||
from homeassistant.components.heos import media_player
|
||||
from homeassistant.components.heos.const import (
|
||||
|
@ -179,7 +179,7 @@ async def test_updates_from_connection_event(
|
|||
event.clear()
|
||||
player.reset_mock()
|
||||
controller.load_players.reset_mock()
|
||||
controller.load_players.side_effect = CommandError(None, "Failure", 1)
|
||||
controller.load_players.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
player.available = True
|
||||
player.heos.dispatcher.send(const.SIGNAL_HEOS_EVENT, const.EVENT_CONNECTED)
|
||||
await event.wait()
|
||||
|
@ -313,7 +313,7 @@ async def test_clear_playlist(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.clear_queue.call_count == 1
|
||||
player.clear_queue.reset_mock()
|
||||
player.clear_queue.side_effect = CommandError(None, "Failure", 1)
|
||||
player.clear_queue.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to clear playlist: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -331,7 +331,7 @@ async def test_pause(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.pause.call_count == 1
|
||||
player.pause.reset_mock()
|
||||
player.pause.side_effect = CommandError(None, "Failure", 1)
|
||||
player.pause.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to pause: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -349,7 +349,7 @@ async def test_play(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.play.call_count == 1
|
||||
player.play.reset_mock()
|
||||
player.play.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to play: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -367,7 +367,7 @@ async def test_previous_track(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.play_previous.call_count == 1
|
||||
player.play_previous.reset_mock()
|
||||
player.play_previous.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play_previous.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to move to previous track: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -385,7 +385,7 @@ async def test_next_track(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.play_next.call_count == 1
|
||||
player.play_next.reset_mock()
|
||||
player.play_next.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play_next.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to move to next track: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -403,7 +403,7 @@ async def test_stop(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.stop.call_count == 1
|
||||
player.stop.reset_mock()
|
||||
player.stop.side_effect = CommandError(None, "Failure", 1)
|
||||
player.stop.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to stop: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -421,7 +421,7 @@ async def test_volume_mute(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
assert player.set_mute.call_count == 1
|
||||
player.set_mute.reset_mock()
|
||||
player.set_mute.side_effect = CommandError(None, "Failure", 1)
|
||||
player.set_mute.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to set mute: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -439,7 +439,7 @@ async def test_shuffle_set(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
player.set_play_mode.assert_called_once_with(player.repeat, True)
|
||||
player.set_play_mode.reset_mock()
|
||||
player.set_play_mode.side_effect = CommandError(None, "Failure", 1)
|
||||
player.set_play_mode.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to set shuffle: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -457,7 +457,7 @@ async def test_volume_set(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
player.set_volume.assert_called_once_with(100)
|
||||
player.set_volume.reset_mock()
|
||||
player.set_volume.side_effect = CommandError(None, "Failure", 1)
|
||||
player.set_volume.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to set volume level: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -516,7 +516,7 @@ async def test_select_radio_favorite_command_error(
|
|||
player = controller.players[1]
|
||||
# Test set radio preset
|
||||
favorite = favorites[2]
|
||||
player.play_favorite.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play_favorite.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
|
@ -575,7 +575,7 @@ async def test_select_input_command_error(
|
|||
await setup_platform(hass, config_entry, config)
|
||||
player = controller.players[1]
|
||||
input_source = input_sources[0]
|
||||
player.play_input_source.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play_input_source.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
|
@ -615,7 +615,7 @@ async def test_play_media_url(hass, config_entry, config, controller, caplog):
|
|||
)
|
||||
player.play_url.assert_called_once_with(url)
|
||||
player.play_url.reset_mock()
|
||||
player.play_url.side_effect = CommandError(None, "Failure", 1)
|
||||
player.play_url.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
assert "Unable to play media: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""Tests for the services module."""
|
||||
from pyheos import CommandError, const
|
||||
from pyheos import CommandFailedError, HeosError, const
|
||||
|
||||
from homeassistant.components.heos.const import (
|
||||
ATTR_PASSWORD,
|
||||
|
@ -51,7 +51,7 @@ async def test_sign_in_not_connected(hass, config_entry, controller, caplog):
|
|||
async def test_sign_in_failed(hass, config_entry, controller, caplog):
|
||||
"""Test sign-in service logs error when not connected."""
|
||||
await setup_component(hass, config_entry)
|
||||
controller.sign_in.side_effect = CommandError("", "Invalid credentials", 6)
|
||||
controller.sign_in.side_effect = CommandFailedError("", "Invalid credentials", 6)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
@ -67,7 +67,7 @@ async def test_sign_in_failed(hass, config_entry, controller, caplog):
|
|||
async def test_sign_in_unknown_error(hass, config_entry, controller, caplog):
|
||||
"""Test sign-in service logs error for failure."""
|
||||
await setup_component(hass, config_entry)
|
||||
controller.sign_in.side_effect = ConnectionError
|
||||
controller.sign_in.side_effect = HeosError()
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
@ -103,7 +103,7 @@ async def test_sign_out_not_connected(hass, config_entry, controller, caplog):
|
|||
async def test_sign_out_unknown_error(hass, config_entry, controller, caplog):
|
||||
"""Test the sign-out service."""
|
||||
await setup_component(hass, config_entry)
|
||||
controller.sign_out.side_effect = ConnectionError
|
||||
controller.sign_out.side_effect = HeosError()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_SIGN_OUT, {}, blocking=True)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue