Skip to content

Commit

Permalink
Rework chromecast fix (#16804)
Browse files Browse the repository at this point in the history
* Revert changes of #16471, and fix the platform setup issue

* Fix unit test

* Fix

* Fix comment

* Fix test

* Address review comment

* Address review comment
  • Loading branch information
awarecan authored and balloob committed Sep 23, 2018
1 parent 329d9df commit 564ad7e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 13 deletions.
20 changes: 11 additions & 9 deletions homeassistant/components/media_player/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@
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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -250,8 +249,8 @@ def async_cast_discovered(discover: ChromecastInfo) -> None:
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]):
Expand All @@ -265,8 +264,11 @@ def async_cast_discovered(discover: ChromecastInfo) -> None:
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)


Expand Down Expand Up @@ -379,7 +381,7 @@ async def async_set_cast_info(self, cast_info):
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
Expand Down
10 changes: 6 additions & 4 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,16 +609,18 @@ def mock_open_f(fname, **_):
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
Expand Down
20 changes: 20 additions & 0 deletions tests/components/media_player/test_cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'}

0 comments on commit 564ad7e

Please sign in to comment.