Catch AndroidTV exception on setup (#86819)

fixes undefined
pull/86985/head
ollo69 2023-01-30 22:42:32 +01:00 committed by GitHub
parent 8337d4613e
commit 772df02cce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 30 deletions

View File

@ -6,6 +6,13 @@ import os
from typing import Any from typing import Any
from adb_shell.auth.keygen import keygen from adb_shell.auth.keygen import keygen
from adb_shell.exceptions import (
AdbTimeoutError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
from androidtv.adb_manager.adb_manager_sync import ADBPythonSync, PythonRSASigner from androidtv.adb_manager.adb_manager_sync import ADBPythonSync, PythonRSASigner
from androidtv.setup_async import ( from androidtv.setup_async import (
AndroidTVAsync, AndroidTVAsync,
@ -43,6 +50,18 @@ from .const import (
SIGNAL_CONFIG_ENTITY, SIGNAL_CONFIG_ENTITY,
) )
ADB_PYTHON_EXCEPTIONS: tuple = (
AdbTimeoutError,
BrokenPipeError,
ConnectionResetError,
ValueError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
ADB_TCP_EXCEPTIONS: tuple = (ConnectionResetError, RuntimeError)
PLATFORMS = [Platform.MEDIA_PLAYER] PLATFORMS = [Platform.MEDIA_PLAYER]
RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES] RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES]
@ -132,9 +151,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Android TV platform.""" """Set up Android TV platform."""
state_det_rules = entry.options.get(CONF_STATE_DETECTION_RULES) state_det_rules = entry.options.get(CONF_STATE_DETECTION_RULES)
aftv, error_message = await async_connect_androidtv( if CONF_ADB_SERVER_IP not in entry.data:
hass, entry.data, state_detection_rules=state_det_rules exceptions = ADB_PYTHON_EXCEPTIONS
) else:
exceptions = ADB_TCP_EXCEPTIONS
try:
aftv, error_message = await async_connect_androidtv(
hass, entry.data, state_detection_rules=state_det_rules
)
except exceptions as exc:
raise ConfigEntryNotReady(exc) from exc
if not aftv: if not aftv:
raise ConfigEntryNotReady(error_message) raise ConfigEntryNotReady(error_message)

View File

@ -7,13 +7,6 @@ import functools
import logging import logging
from typing import Any, Concatenate, ParamSpec, TypeVar from typing import Any, Concatenate, ParamSpec, TypeVar
from adb_shell.exceptions import (
AdbTimeoutError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
from androidtv.constants import APPS, KEYS from androidtv.constants import APPS, KEYS
from androidtv.exceptions import LockNotAcquiredException from androidtv.exceptions import LockNotAcquiredException
import voluptuous as vol import voluptuous as vol
@ -42,7 +35,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import get_androidtv_mac from . import ADB_PYTHON_EXCEPTIONS, ADB_TCP_EXCEPTIONS, get_androidtv_mac
from .const import ( from .const import (
ANDROID_DEV, ANDROID_DEV,
ANDROID_DEV_OPT, ANDROID_DEV_OPT,
@ -252,19 +245,10 @@ class ADBDevice(MediaPlayerEntity):
# ADB exceptions to catch # ADB exceptions to catch
if not aftv.adb_server_ip: if not aftv.adb_server_ip:
# Using "adb_shell" (Python ADB implementation) # Using "adb_shell" (Python ADB implementation)
self.exceptions = ( self.exceptions = ADB_PYTHON_EXCEPTIONS
AdbTimeoutError,
BrokenPipeError,
ConnectionResetError,
ValueError,
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
else: else:
# Using "pure-python-adb" (communicate with ADB server) # Using "pure-python-adb" (communicate with ADB server)
self.exceptions = (ConnectionResetError, RuntimeError) self.exceptions = ADB_TCP_EXCEPTIONS
# Property attributes # Property attributes
self._attr_extra_state_attributes = { self._attr_extra_state_attributes = {

View File

@ -111,7 +111,7 @@ def patch_connect(success):
} }
def patch_shell(response=None, error=False, mac_eth=False): def patch_shell(response=None, error=False, mac_eth=False, exc=None):
"""Mock the `AdbDeviceTcpAsyncFake.shell` and `DeviceAsyncFake.shell` methods.""" """Mock the `AdbDeviceTcpAsyncFake.shell` and `DeviceAsyncFake.shell` methods."""
async def shell_success(self, cmd, *args, **kwargs): async def shell_success(self, cmd, *args, **kwargs):
@ -128,7 +128,7 @@ def patch_shell(response=None, error=False, mac_eth=False):
async def shell_fail_python(self, cmd, *args, **kwargs): async def shell_fail_python(self, cmd, *args, **kwargs):
"""Mock the `AdbDeviceTcpAsyncFake.shell` method when it fails.""" """Mock the `AdbDeviceTcpAsyncFake.shell` method when it fails."""
self.shell_cmd = cmd self.shell_cmd = cmd
raise ValueError raise exc or ValueError
async def shell_fail_server(self, cmd): async def shell_fail_server(self, cmd):
"""Mock the `DeviceAsyncFake.shell` method when it fails.""" """Mock the `DeviceAsyncFake.shell` method when it fails."""

View File

@ -2,6 +2,7 @@
import logging import logging
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from adb_shell.exceptions import TcpTimeoutException as AdbShellTimeoutException
from androidtv.constants import APPS as ANDROIDTV_APPS, KEYS from androidtv.constants import APPS as ANDROIDTV_APPS, KEYS
from androidtv.exceptions import LockNotAcquiredException from androidtv.exceptions import LockNotAcquiredException
import pytest import pytest
@ -538,25 +539,28 @@ async def test_select_source_firetv(hass, source, expected_arg, method_patch):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", ["config", "connect"],
[ [
CONFIG_ANDROIDTV_DEFAULT, (CONFIG_ANDROIDTV_DEFAULT, False),
CONFIG_FIRETV_DEFAULT, (CONFIG_FIRETV_DEFAULT, False),
(CONFIG_ANDROIDTV_DEFAULT, True),
(CONFIG_FIRETV_DEFAULT, True),
], ],
) )
async def test_setup_fail(hass, config): async def test_setup_fail(hass, config, connect):
"""Test that the entity is not created when the ADB connection is not established.""" """Test that the entity is not created when the ADB connection is not established."""
patch_key, entity_id, config_entry = _setup(config) patch_key, entity_id, config_entry = _setup(config)
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
with patchers.patch_connect(False)[patch_key], patchers.patch_shell( with patchers.patch_connect(connect)[patch_key], patchers.patch_shell(
SHELL_RESPONSE_OFF SHELL_RESPONSE_OFF, error=True, exc=AdbShellTimeoutException
)[patch_key]: )[patch_key]:
assert await hass.config_entries.async_setup(config_entry.entry_id) is False assert await hass.config_entries.async_setup(config_entry.entry_id) is False
await hass.async_block_till_done() await hass.async_block_till_done()
await async_update_entity(hass, entity_id) await async_update_entity(hass, entity_id)
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert config_entry.state == ConfigEntryState.SETUP_RETRY
assert state is None assert state is None