diff --git a/homeassistant/components/directv/__init__.py b/homeassistant/components/directv/__init__.py index d9f3f171992..fc7bb78989a 100644 --- a/homeassistant/components/directv/__init__.py +++ b/homeassistant/components/directv/__init__.py @@ -32,7 +32,7 @@ def get_dtv_data( hass: HomeAssistant, host: str, port: int = DEFAULT_PORT, client_addr: str = "0" ) -> dict: """Retrieve a DIRECTV instance, locations list, and version info for the receiver device.""" - dtv = DIRECTV(host, port, client_addr) + dtv = DIRECTV(host, port, client_addr, determine_state=False) locations = dtv.get_locations() version_info = dtv.get_version() diff --git a/homeassistant/components/directv/config_flow.py b/homeassistant/components/directv/config_flow.py index 27ddf2cda7b..d1b3a6cbe62 100644 --- a/homeassistant/components/directv/config_flow.py +++ b/homeassistant/components/directv/config_flow.py @@ -29,8 +29,7 @@ def validate_input(data: Dict) -> Dict: Data has the keys from DATA_SCHEMA with values provided by the user. """ - # directpy does IO in constructor. - dtv = DIRECTV(data["host"], DEFAULT_PORT) + dtv = DIRECTV(data["host"], DEFAULT_PORT, determine_state=False) version_info = dtv.get_version() return { @@ -76,8 +75,7 @@ class DirecTVConfigFlow(ConfigFlow, domain=DOMAIN): return self._show_form(errors) except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception") - errors["base"] = ERROR_UNKNOWN - return self._show_form(errors) + return self.async_abort(reason=ERROR_UNKNOWN) await self.async_set_unique_id(info["receiver_id"]) self._abort_if_unique_id_configured() diff --git a/homeassistant/components/directv/media_player.py b/homeassistant/components/directv/media_player.py index c1c227d319d..b04ef9fed68 100644 --- a/homeassistant/components/directv/media_player.py +++ b/homeassistant/components/directv/media_player.py @@ -83,22 +83,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ) -def get_dtv_instance( - host: str, port: int = DEFAULT_PORT, client_addr: str = "0" -) -> DIRECTV: - """Retrieve a DIRECTV instance for the receiver or client device.""" - try: - return DIRECTV(host, port, client_addr) - except RequestException as exception: - _LOGGER.debug( - "Request exception %s trying to retrieve DIRECTV instance for client address %s on device %s", - exception, - client_addr, - host, - ) - return None - - async def async_setup_entry( hass: HomeAssistantType, entry: ConfigEntry, @@ -114,16 +98,15 @@ async def async_setup_entry( continue if loc["clientAddr"] != "0": - # directpy does IO in constructor. - dtv = await hass.async_add_executor_job( - get_dtv_instance, entry.data[CONF_HOST], DEFAULT_PORT, loc["clientAddr"] + dtv = DIRECTV( + entry.data[CONF_HOST], + DEFAULT_PORT, + loc["clientAddr"], + determine_state=False, ) else: dtv = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT] - if not dtv: - continue - entities.append( DirecTvDevice( str.title(loc["locationName"]), loc["clientAddr"], dtv, version_info, diff --git a/tests/components/directv/__init__.py b/tests/components/directv/__init__.py index d7f79c76be5..876b1e311ab 100644 --- a/tests/components/directv/__init__.py +++ b/tests/components/directv/__init__.py @@ -1,4 +1,6 @@ """Tests for the DirecTV component.""" +from DirectPy import DIRECTV + from homeassistant.components.directv.const import DOMAIN from homeassistant.const import CONF_HOST from homeassistant.helpers.typing import HomeAssistantType @@ -94,18 +96,23 @@ MOCK_GET_VERSION = { } -class MockDirectvClass: +class MockDirectvClass(DIRECTV): """A fake DirecTV DVR device.""" - def __init__(self, ip, port=8080, clientAddr="0"): + def __init__(self, ip, port=8080, clientAddr="0", determine_state=False): """Initialize the fake DirecTV device.""" - self._host = ip - self._port = port - self._device = clientAddr - self._standby = True - self._play = False + super().__init__( + ip=ip, port=port, clientAddr=clientAddr, determine_state=determine_state, + ) - self.attributes = LIVE + self._play = False + self._standby = True + + if self.clientAddr == CLIENT_ADDRESS: + self.attributes = RECORDING + self._standby = False + else: + self.attributes = LIVE def get_locations(self): """Mock for get_locations method.""" diff --git a/tests/components/directv/test_config_flow.py b/tests/components/directv/test_config_flow.py index 5516b61cd46..bd5d8b83419 100644 --- a/tests/components/directv/test_config_flow.py +++ b/tests/components/directv/test_config_flow.py @@ -114,9 +114,7 @@ async def test_form_cannot_connect(hass: HomeAssistantType) -> None: ) with patch( - "homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.config_flow.DIRECTV.get_version", + "tests.components.directv.test_config_flow.MockDirectvClass.get_version", side_effect=RequestException, ) as mock_validate_input: result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST},) @@ -135,15 +133,13 @@ async def test_form_unknown_error(hass: HomeAssistantType) -> None: ) with patch( - "homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.config_flow.DIRECTV.get_version", + "tests.components.directv.test_config_flow.MockDirectvClass.get_version", side_effect=Exception, ) as mock_validate_input: result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST},) - assert result["type"] == RESULT_TYPE_FORM - assert result["errors"] == {"base": "unknown"} + assert result["type"] == RESULT_TYPE_ABORT + assert result["reason"] == "unknown" await hass.async_block_till_done() assert len(mock_validate_input.mock_calls) == 1 @@ -205,9 +201,7 @@ async def test_ssdp_discovery_confirm_abort(hass: HomeAssistantType) -> None: ) with patch( - "homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.config_flow.DIRECTV.get_version", + "tests.components.directv.test_config_flow.MockDirectvClass.get_version", side_effect=RequestException, ) as mock_validate_input: result = await async_configure_flow(hass, result["flow_id"], {}) @@ -227,9 +221,7 @@ async def test_ssdp_discovery_confirm_unknown_error(hass: HomeAssistantType) -> ) with patch( - "homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.config_flow.DIRECTV.get_version", + "tests.components.directv.test_config_flow.MockDirectvClass.get_version", side_effect=Exception, ) as mock_validate_input: result = await async_configure_flow(hass, result["flow_id"], {}) diff --git a/tests/components/directv/test_media_player.py b/tests/components/directv/test_media_player.py index 9c06164c309..f7cf63355a8 100644 --- a/tests/components/directv/test_media_player.py +++ b/tests/components/directv/test_media_player.py @@ -54,9 +54,7 @@ from homeassistant.util import dt as dt_util from tests.common import MockConfigEntry, async_fire_time_changed from tests.components.directv import ( - CLIENT_ADDRESS, DOMAIN, - HOST, MOCK_GET_LOCATIONS_MULTIPLE, RECORDING, MockDirectvClass, @@ -70,15 +68,6 @@ MAIN_ENTITY_ID = f"{MP_DOMAIN}.main_dvr" # pylint: disable=redefined-outer-name -@fixture -def client_dtv() -> MockDirectvClass: - """Fixture for a client device.""" - mocked_dtv = MockDirectvClass(HOST, clientAddr=CLIENT_ADDRESS) - mocked_dtv.attributes = RECORDING - mocked_dtv._standby = False # pylint: disable=protected-access - return mocked_dtv - - @fixture def mock_now() -> datetime: """Fixture for dtutil.now.""" @@ -93,34 +82,19 @@ async def setup_directv(hass: HomeAssistantType) -> MockConfigEntry: return await setup_integration(hass) -async def setup_directv_with_instance_error(hass: HomeAssistantType) -> MockConfigEntry: +async def setup_directv_with_locations(hass: HomeAssistantType) -> MockConfigEntry: """Set up mock DirecTV integration.""" with patch( - "homeassistant.components.directv.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.DIRECTV.get_locations", + "tests.components.directv.test_media_player.MockDirectvClass.get_locations", return_value=MOCK_GET_LOCATIONS_MULTIPLE, - ), patch( - "homeassistant.components.directv.media_player.get_dtv_instance", - return_value=None, ): - return await setup_integration(hass) - - -async def setup_directv_with_locations( - hass: HomeAssistantType, client_dtv: MockDirectvClass, -) -> MockConfigEntry: - """Set up mock DirecTV integration.""" - with patch( - "homeassistant.components.directv.DIRECTV", new=MockDirectvClass, - ), patch( - "homeassistant.components.directv.DIRECTV.get_locations", - return_value=MOCK_GET_LOCATIONS_MULTIPLE, - ), patch( - "homeassistant.components.directv.media_player.get_dtv_instance", - return_value=client_dtv, - ): - return await setup_integration(hass) + with patch( + "homeassistant.components.directv.DIRECTV", new=MockDirectvClass, + ), patch( + "homeassistant.components.directv.media_player.DIRECTV", + new=MockDirectvClass, + ): + return await setup_integration(hass) async def async_turn_on( @@ -204,27 +178,17 @@ async def test_setup(hass: HomeAssistantType) -> None: assert hass.states.get(MAIN_ENTITY_ID) -async def test_setup_with_multiple_locations( - hass: HomeAssistantType, client_dtv: MockDirectvClass -) -> None: +async def test_setup_with_multiple_locations(hass: HomeAssistantType) -> None: """Test setup with basic config with client location.""" - await setup_directv_with_locations(hass, client_dtv) + await setup_directv_with_locations(hass) assert hass.states.get(MAIN_ENTITY_ID) assert hass.states.get(CLIENT_ENTITY_ID) -async def test_setup_with_instance_error(hass: HomeAssistantType) -> None: - """Test setup with basic config with client location that results in instance error.""" - await setup_directv_with_instance_error(hass) - - assert hass.states.get(MAIN_ENTITY_ID) - assert hass.states.async_entity_ids(MP_DOMAIN) == [MAIN_ENTITY_ID] - - -async def test_unique_id(hass: HomeAssistantType, client_dtv: MockDirectvClass) -> None: +async def test_unique_id(hass: HomeAssistantType) -> None: """Test unique id.""" - await setup_directv_with_locations(hass, client_dtv) + await setup_directv_with_locations(hass) entity_registry = await hass.helpers.entity_registry.async_get_registry() @@ -235,11 +199,9 @@ async def test_unique_id(hass: HomeAssistantType, client_dtv: MockDirectvClass) assert client.unique_id == "2CA17D1CD30X" -async def test_supported_features( - hass: HomeAssistantType, client_dtv: MockDirectvClass -) -> None: +async def test_supported_features(hass: HomeAssistantType) -> None: """Test supported features.""" - await setup_directv_with_locations(hass, client_dtv) + await setup_directv_with_locations(hass) # Features supported for main DVR state = hass.states.get(MAIN_ENTITY_ID) @@ -269,10 +231,10 @@ async def test_supported_features( async def test_check_attributes( - hass: HomeAssistantType, mock_now: dt_util.dt.datetime, client_dtv: MockDirectvClass + hass: HomeAssistantType, mock_now: dt_util.dt.datetime ) -> None: """Test attributes.""" - await setup_directv_with_locations(hass, client_dtv) + await setup_directv_with_locations(hass) next_update = mock_now + timedelta(minutes=5) with patch("homeassistant.util.dt.utcnow", return_value=next_update): @@ -321,10 +283,10 @@ async def test_check_attributes( async def test_main_services( - hass: HomeAssistantType, mock_now: dt_util.dt.datetime, client_dtv: MockDirectvClass + hass: HomeAssistantType, mock_now: dt_util.dt.datetime ) -> None: """Test the different services.""" - await setup_directv_with_locations(hass, client_dtv) + await setup_directv(hass) next_update = mock_now + timedelta(minutes=5) with patch("homeassistant.util.dt.utcnow", return_value=next_update): @@ -373,10 +335,10 @@ async def test_main_services( async def test_available( - hass: HomeAssistantType, mock_now: dt_util.dt.datetime, client_dtv: MockDirectvClass + hass: HomeAssistantType, mock_now: dt_util.dt.datetime ) -> None: """Test available status.""" - entry = await setup_directv_with_locations(hass, client_dtv) + entry = await setup_directv(hass) next_update = mock_now + timedelta(minutes=5) with patch("homeassistant.util.dt.utcnow", return_value=next_update):