mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 07:37:34 +00:00
Optimize directv client initialization (#32706)
* Optimize directv client initialization. * Update config_flow.py * Update media_player.py * Update media_player.py * Update __init__.py * Update __init__.py * Update __init__.py * Update __init__.py * Update test_media_player.py * Update __init__.py * Update media_player.py * Update test_media_player.py * Update media_player.py * Update test_media_player.py * Update config_flow.py * Update test_config_flow.py * Update test_config_flow.py * Update test_config_flow.py * Update test_config_flow.py * Update test_config_flow.py * Update test_config_flow.py * Update __init__.py * Update test_config_flow.py * Update test_config_flow.py * Update test_media_player.py * Update test_media_player.py * Update __init__.py * Update __init__.py * Update __init__.py
This commit is contained in:
parent
750ed2facd
commit
5dd031af17
@ -32,7 +32,7 @@ def get_dtv_data(
|
|||||||
hass: HomeAssistant, host: str, port: int = DEFAULT_PORT, client_addr: str = "0"
|
hass: HomeAssistant, host: str, port: int = DEFAULT_PORT, client_addr: str = "0"
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Retrieve a DIRECTV instance, locations list, and version info for the receiver device."""
|
"""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()
|
locations = dtv.get_locations()
|
||||||
version_info = dtv.get_version()
|
version_info = dtv.get_version()
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@ def validate_input(data: Dict) -> Dict:
|
|||||||
|
|
||||||
Data has the keys from DATA_SCHEMA with values provided by the user.
|
Data has the keys from DATA_SCHEMA with values provided by the user.
|
||||||
"""
|
"""
|
||||||
# directpy does IO in constructor.
|
dtv = DIRECTV(data["host"], DEFAULT_PORT, determine_state=False)
|
||||||
dtv = DIRECTV(data["host"], DEFAULT_PORT)
|
|
||||||
version_info = dtv.get_version()
|
version_info = dtv.get_version()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -76,8 +75,7 @@ class DirecTVConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return self._show_form(errors)
|
return self._show_form(errors)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception("Unexpected exception")
|
_LOGGER.exception("Unexpected exception")
|
||||||
errors["base"] = ERROR_UNKNOWN
|
return self.async_abort(reason=ERROR_UNKNOWN)
|
||||||
return self._show_form(errors)
|
|
||||||
|
|
||||||
await self.async_set_unique_id(info["receiver_id"])
|
await self.async_set_unique_id(info["receiver_id"])
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
|
@ -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(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
@ -114,16 +98,15 @@ async def async_setup_entry(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if loc["clientAddr"] != "0":
|
if loc["clientAddr"] != "0":
|
||||||
# directpy does IO in constructor.
|
dtv = DIRECTV(
|
||||||
dtv = await hass.async_add_executor_job(
|
entry.data[CONF_HOST],
|
||||||
get_dtv_instance, entry.data[CONF_HOST], DEFAULT_PORT, loc["clientAddr"]
|
DEFAULT_PORT,
|
||||||
|
loc["clientAddr"],
|
||||||
|
determine_state=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
dtv = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT]
|
dtv = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT]
|
||||||
|
|
||||||
if not dtv:
|
|
||||||
continue
|
|
||||||
|
|
||||||
entities.append(
|
entities.append(
|
||||||
DirecTvDevice(
|
DirecTvDevice(
|
||||||
str.title(loc["locationName"]), loc["clientAddr"], dtv, version_info,
|
str.title(loc["locationName"]), loc["clientAddr"], dtv, version_info,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
"""Tests for the DirecTV component."""
|
"""Tests for the DirecTV component."""
|
||||||
|
from DirectPy import DIRECTV
|
||||||
|
|
||||||
from homeassistant.components.directv.const import DOMAIN
|
from homeassistant.components.directv.const import DOMAIN
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
@ -94,17 +96,22 @@ MOCK_GET_VERSION = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MockDirectvClass:
|
class MockDirectvClass(DIRECTV):
|
||||||
"""A fake DirecTV DVR device."""
|
"""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."""
|
"""Initialize the fake DirecTV device."""
|
||||||
self._host = ip
|
super().__init__(
|
||||||
self._port = port
|
ip=ip, port=port, clientAddr=clientAddr, determine_state=determine_state,
|
||||||
self._device = clientAddr
|
)
|
||||||
self._standby = True
|
|
||||||
self._play = False
|
|
||||||
|
|
||||||
|
self._play = False
|
||||||
|
self._standby = True
|
||||||
|
|
||||||
|
if self.clientAddr == CLIENT_ADDRESS:
|
||||||
|
self.attributes = RECORDING
|
||||||
|
self._standby = False
|
||||||
|
else:
|
||||||
self.attributes = LIVE
|
self.attributes = LIVE
|
||||||
|
|
||||||
def get_locations(self):
|
def get_locations(self):
|
||||||
|
@ -114,9 +114,7 @@ async def test_form_cannot_connect(hass: HomeAssistantType) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass,
|
"tests.components.directv.test_config_flow.MockDirectvClass.get_version",
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV.get_version",
|
|
||||||
side_effect=RequestException,
|
side_effect=RequestException,
|
||||||
) as mock_validate_input:
|
) as mock_validate_input:
|
||||||
result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST},)
|
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(
|
with patch(
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass,
|
"tests.components.directv.test_config_flow.MockDirectvClass.get_version",
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV.get_version",
|
|
||||||
side_effect=Exception,
|
side_effect=Exception,
|
||||||
) as mock_validate_input:
|
) as mock_validate_input:
|
||||||
result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST},)
|
result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST},)
|
||||||
|
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_ABORT
|
||||||
assert result["errors"] == {"base": "unknown"}
|
assert result["reason"] == "unknown"
|
||||||
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(mock_validate_input.mock_calls) == 1
|
assert len(mock_validate_input.mock_calls) == 1
|
||||||
@ -205,9 +201,7 @@ async def test_ssdp_discovery_confirm_abort(hass: HomeAssistantType) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass,
|
"tests.components.directv.test_config_flow.MockDirectvClass.get_version",
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV.get_version",
|
|
||||||
side_effect=RequestException,
|
side_effect=RequestException,
|
||||||
) as mock_validate_input:
|
) as mock_validate_input:
|
||||||
result = await async_configure_flow(hass, result["flow_id"], {})
|
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(
|
with patch(
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV", new=MockDirectvClass,
|
"tests.components.directv.test_config_flow.MockDirectvClass.get_version",
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.config_flow.DIRECTV.get_version",
|
|
||||||
side_effect=Exception,
|
side_effect=Exception,
|
||||||
) as mock_validate_input:
|
) as mock_validate_input:
|
||||||
result = await async_configure_flow(hass, result["flow_id"], {})
|
result = await async_configure_flow(hass, result["flow_id"], {})
|
||||||
|
@ -54,9 +54,7 @@ from homeassistant.util import dt as dt_util
|
|||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
from tests.components.directv import (
|
from tests.components.directv import (
|
||||||
CLIENT_ADDRESS,
|
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
HOST,
|
|
||||||
MOCK_GET_LOCATIONS_MULTIPLE,
|
MOCK_GET_LOCATIONS_MULTIPLE,
|
||||||
RECORDING,
|
RECORDING,
|
||||||
MockDirectvClass,
|
MockDirectvClass,
|
||||||
@ -70,15 +68,6 @@ MAIN_ENTITY_ID = f"{MP_DOMAIN}.main_dvr"
|
|||||||
# pylint: disable=redefined-outer-name
|
# 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
|
@fixture
|
||||||
def mock_now() -> datetime:
|
def mock_now() -> datetime:
|
||||||
"""Fixture for dtutil.now."""
|
"""Fixture for dtutil.now."""
|
||||||
@ -93,32 +82,17 @@ async def setup_directv(hass: HomeAssistantType) -> MockConfigEntry:
|
|||||||
return await setup_integration(hass)
|
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."""
|
"""Set up mock DirecTV integration."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.directv.DIRECTV", new=MockDirectvClass,
|
"tests.components.directv.test_media_player.MockDirectvClass.get_locations",
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.DIRECTV.get_locations",
|
|
||||||
return_value=MOCK_GET_LOCATIONS_MULTIPLE,
|
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(
|
with patch(
|
||||||
"homeassistant.components.directv.DIRECTV", new=MockDirectvClass,
|
"homeassistant.components.directv.DIRECTV", new=MockDirectvClass,
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.directv.DIRECTV.get_locations",
|
"homeassistant.components.directv.media_player.DIRECTV",
|
||||||
return_value=MOCK_GET_LOCATIONS_MULTIPLE,
|
new=MockDirectvClass,
|
||||||
), patch(
|
|
||||||
"homeassistant.components.directv.media_player.get_dtv_instance",
|
|
||||||
return_value=client_dtv,
|
|
||||||
):
|
):
|
||||||
return await setup_integration(hass)
|
return await setup_integration(hass)
|
||||||
|
|
||||||
@ -204,27 +178,17 @@ async def test_setup(hass: HomeAssistantType) -> None:
|
|||||||
assert hass.states.get(MAIN_ENTITY_ID)
|
assert hass.states.get(MAIN_ENTITY_ID)
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_with_multiple_locations(
|
async def test_setup_with_multiple_locations(hass: HomeAssistantType) -> None:
|
||||||
hass: HomeAssistantType, client_dtv: MockDirectvClass
|
|
||||||
) -> None:
|
|
||||||
"""Test setup with basic config with client location."""
|
"""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(MAIN_ENTITY_ID)
|
||||||
assert hass.states.get(CLIENT_ENTITY_ID)
|
assert hass.states.get(CLIENT_ENTITY_ID)
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_with_instance_error(hass: HomeAssistantType) -> None:
|
async def test_unique_id(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:
|
|
||||||
"""Test unique id."""
|
"""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()
|
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"
|
assert client.unique_id == "2CA17D1CD30X"
|
||||||
|
|
||||||
|
|
||||||
async def test_supported_features(
|
async def test_supported_features(hass: HomeAssistantType) -> None:
|
||||||
hass: HomeAssistantType, client_dtv: MockDirectvClass
|
|
||||||
) -> None:
|
|
||||||
"""Test supported features."""
|
"""Test supported features."""
|
||||||
await setup_directv_with_locations(hass, client_dtv)
|
await setup_directv_with_locations(hass)
|
||||||
|
|
||||||
# Features supported for main DVR
|
# Features supported for main DVR
|
||||||
state = hass.states.get(MAIN_ENTITY_ID)
|
state = hass.states.get(MAIN_ENTITY_ID)
|
||||||
@ -269,10 +231,10 @@ async def test_supported_features(
|
|||||||
|
|
||||||
|
|
||||||
async def test_check_attributes(
|
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:
|
) -> None:
|
||||||
"""Test attributes."""
|
"""Test attributes."""
|
||||||
await setup_directv_with_locations(hass, client_dtv)
|
await setup_directv_with_locations(hass)
|
||||||
|
|
||||||
next_update = mock_now + timedelta(minutes=5)
|
next_update = mock_now + timedelta(minutes=5)
|
||||||
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
||||||
@ -321,10 +283,10 @@ async def test_check_attributes(
|
|||||||
|
|
||||||
|
|
||||||
async def test_main_services(
|
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:
|
) -> None:
|
||||||
"""Test the different services."""
|
"""Test the different services."""
|
||||||
await setup_directv_with_locations(hass, client_dtv)
|
await setup_directv(hass)
|
||||||
|
|
||||||
next_update = mock_now + timedelta(minutes=5)
|
next_update = mock_now + timedelta(minutes=5)
|
||||||
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
||||||
@ -373,10 +335,10 @@ async def test_main_services(
|
|||||||
|
|
||||||
|
|
||||||
async def test_available(
|
async def test_available(
|
||||||
hass: HomeAssistantType, mock_now: dt_util.dt.datetime, client_dtv: MockDirectvClass
|
hass: HomeAssistantType, mock_now: dt_util.dt.datetime
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test available status."""
|
"""Test available status."""
|
||||||
entry = await setup_directv_with_locations(hass, client_dtv)
|
entry = await setup_directv(hass)
|
||||||
|
|
||||||
next_update = mock_now + timedelta(minutes=5)
|
next_update = mock_now + timedelta(minutes=5)
|
||||||
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
with patch("homeassistant.util.dt.utcnow", return_value=next_update):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user