Rework chromecast fix (#16804)

* Revert changes of #16471, and fix the platform setup issue

* Fix unit test

* Fix

* Fix comment

* Fix test

* Address review comment

* Address review comment
pull/16812/head
Jason Hu 2018-09-23 14:35:07 -07:00 committed by Paulus Schoutsen
parent 329d9dfc06
commit 564ad7e22a
3 changed files with 37 additions and 13 deletions

View File

@ -61,10 +61,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.All(cv.ensure_list, [cv.string]),
})
CONNECTION_RETRY = 3
CONNECTION_RETRY_WAIT = 2
CONNECTION_TIMEOUT = 10
@attr.s(slots=True, frozen=True)
class ChromecastInfo:
@ -216,9 +212,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if not isinstance(config, list):
config = [config]
await asyncio.wait([
# no pending task
done, _ = await asyncio.wait([
_async_setup_platform(hass, cfg, async_add_entities, None)
for cfg in config])
if any([task.exception() for task in done]):
raise PlatformNotReady
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
@ -250,8 +249,8 @@ async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
if cast_device is not None:
async_add_entities([cast_device])
async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
async_cast_discovered)
remove_handler = async_dispatcher_connect(
hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered)
# Re-play the callback for all past chromecasts, store the objects in
# a list to avoid concurrent modification resulting in exception.
for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]):
@ -265,8 +264,11 @@ async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
info = await hass.async_add_job(_fill_out_missing_chromecast_info,
info)
if info.friendly_name is None:
# HTTP dial failed, so we won't be able to connect.
_LOGGER.debug("Cannot retrieve detail information for chromecast"
" %s, the device may not be online", info)
remove_handler()
raise PlatformNotReady
hass.async_add_job(_discover_chromecast, hass, info)
@ -379,7 +381,7 @@ class CastDevice(MediaPlayerDevice):
pychromecast._get_chromecast_from_host, (
cast_info.host, cast_info.port, cast_info.uuid,
cast_info.model_name, cast_info.friendly_name
), CONNECTION_RETRY, CONNECTION_RETRY_WAIT, CONNECTION_TIMEOUT)
))
self._chromecast = chromecast
self._status_listener = CastStatusListener(self, chromecast)
# Initialise connection status as connected because we can only

View File

@ -609,16 +609,18 @@ def patch_yaml_files(files_dict, endswith=True):
return patch.object(yaml, 'open', mock_open_f, create=True)
def mock_coro(return_value=None):
"""Return a coro that returns a value."""
return mock_coro_func(return_value)()
def mock_coro(return_value=None, exception=None):
"""Return a coro that returns a value or raise an exception."""
return mock_coro_func(return_value, exception)()
def mock_coro_func(return_value=None):
def mock_coro_func(return_value=None, exception=None):
"""Return a method to create a coro function that returns a value."""
@asyncio.coroutine
def coro(*args, **kwargs):
"""Fake coroutine."""
if exception:
raise exception
return return_value
return coro

View File

@ -415,3 +415,23 @@ async def test_entry_setup_list_config(hass: HomeAssistantType):
assert len(mock_setup.mock_calls) == 2
assert mock_setup.mock_calls[0][1][1] == {'host': 'bla'}
assert mock_setup.mock_calls[1][1][1] == {'host': 'blu'}
async def test_entry_setup_platform_not_ready(hass: HomeAssistantType):
"""Test failed setting up entry will raise PlatformNotReady."""
await async_setup_component(hass, 'cast', {
'cast': {
'media_player': {
'host': 'bla'
}
}
})
with patch(
'homeassistant.components.media_player.cast._async_setup_platform',
return_value=mock_coro(exception=Exception)) as mock_setup:
with pytest.raises(PlatformNotReady):
await cast.async_setup_entry(hass, MockConfigEntry(), None)
assert len(mock_setup.mock_calls) == 1
assert mock_setup.mock_calls[0][1][1] == {'host': 'bla'}