Bump androidtv to 0.0.28 (#26906)

* Bump androidtv to 0.0.28

* Address reviewer comments

* Remove adb-shell from requirements_test_all.txt

* Use a one-liner to avoid a coverage failure
This commit is contained in:
Jeff Irion 2019-09-26 22:53:26 -07:00 committed by Martin Hjelmare
parent b04a70995e
commit 45c548ae47
6 changed files with 61 additions and 52 deletions

View file

@ -3,7 +3,8 @@
"name": "Androidtv",
"documentation": "https://www.home-assistant.io/components/androidtv",
"requirements": [
"androidtv==0.0.27"
"adb-shell==0.0.2",
"androidtv==0.0.28"
],
"dependencies": [],
"codeowners": ["@JeffLIrion"]

View file

@ -3,6 +3,12 @@ import functools
import logging
import voluptuous as vol
from adb_shell.exceptions import (
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
TcpTimeoutException,
)
from androidtv import setup, ha_state_detection_rules_validator
from androidtv.constants import APPS, KEYS
@ -123,11 +129,15 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Android TV / Fire TV platform."""
hass.data.setdefault(ANDROIDTV_DOMAIN, {})
host = "{0}:{1}".format(config[CONF_HOST], config[CONF_PORT])
host = f"{config[CONF_HOST]}:{config[CONF_PORT]}"
if CONF_ADB_SERVER_IP not in config:
# Use "python-adb" (Python ADB implementation)
adb_log = "using Python ADB implementation "
# Use "adb_shell" (Python ADB implementation)
adb_log = "using Python ADB implementation " + (
f"with adbkey='{config[CONF_ADBKEY]}'"
if CONF_ADBKEY in config
else "without adbkey authentication"
)
if CONF_ADBKEY in config:
aftv = setup(
host,
@ -135,7 +145,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
device_class=config[CONF_DEVICE_CLASS],
state_detection_rules=config[CONF_STATE_DETECTION_RULES],
)
adb_log += "with adbkey='{0}'".format(config[CONF_ADBKEY])
else:
aftv = setup(
@ -143,7 +152,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
device_class=config[CONF_DEVICE_CLASS],
state_detection_rules=config[CONF_STATE_DETECTION_RULES],
)
adb_log += "without adbkey authentication"
else:
# Use "pure-python-adb" (communicate with ADB server)
aftv = setup(
@ -153,9 +161,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
device_class=config[CONF_DEVICE_CLASS],
state_detection_rules=config[CONF_STATE_DETECTION_RULES],
)
adb_log = "using ADB server at {0}:{1}".format(
config[CONF_ADB_SERVER_IP], config[CONF_ADB_SERVER_PORT]
)
adb_log = f"using ADB server at {config[CONF_ADB_SERVER_IP]}:{config[CONF_ADB_SERVER_PORT]}"
if not aftv.available:
# Determine the name that will be used for the device in the log
@ -251,6 +257,7 @@ def adb_decorator(override_available=False):
"establishing attempt in the next update. Error: %s",
err,
)
self.aftv.adb.close()
self._available = False # pylint: disable=protected-access
return None
@ -278,14 +285,7 @@ class ADBDevice(MediaPlayerDevice):
# ADB exceptions to catch
if not self.aftv.adb_server_ip:
# Using "python-adb" (Python ADB implementation)
from adb.adb_protocol import (
InvalidChecksumError,
InvalidCommandError,
InvalidResponseError,
)
from adb.usb_exceptions import TcpTimeoutException
# Using "adb_shell" (Python ADB implementation)
self.exceptions = (
AttributeError,
BrokenPipeError,

View file

@ -111,6 +111,9 @@ adafruit-blinka==1.2.1
# homeassistant.components.mcp23017
adafruit-circuitpython-mcp230xx==1.1.2
# homeassistant.components.androidtv
adb-shell==0.0.2
# homeassistant.components.adguard
adguardhome==0.2.1
@ -197,7 +200,7 @@ ambiclimate==0.2.1
amcrest==1.5.3
# homeassistant.components.androidtv
androidtv==0.0.27
androidtv==0.0.28
# homeassistant.components.anel_pwrctrl
anel_pwrctrl-homeassistant==0.0.1.dev2

View file

@ -80,7 +80,7 @@ aiowwlln==2.0.2
ambiclimate==0.2.1
# homeassistant.components.androidtv
androidtv==0.0.27
androidtv==0.0.28
# homeassistant.components.apns
apns2==0.3.0

View file

@ -4,34 +4,24 @@ from socket import error as socket_error
from unittest.mock import patch
class AdbCommandsFake:
"""A fake of the `adb.adb_commands.AdbCommands` class."""
class AdbDeviceFake:
"""A fake of the `adb_shell.adb_device.AdbDevice` class."""
def ConnectDevice(self, *args, **kwargs): # pylint: disable=invalid-name
def __init__(self, *args, **kwargs):
"""Initialize a fake `adb_shell.adb_device.AdbDevice` instance."""
self.available = False
def close(self):
"""Close the socket connection."""
self.available = False
def connect(self, *args, **kwargs):
"""Try to connect to a device."""
raise NotImplementedError
def Shell(self, cmd): # pylint: disable=invalid-name
def shell(self, cmd):
"""Send an ADB shell command."""
raise NotImplementedError
class AdbCommandsFakeSuccess(AdbCommandsFake):
"""A fake of the `adb.adb_commands.AdbCommands` class when the connection attempt succeeds."""
def ConnectDevice(self, *args, **kwargs): # pylint: disable=invalid-name
"""Successfully connect to a device."""
return self
class AdbCommandsFakeFail(AdbCommandsFake):
"""A fake of the `adb.adb_commands.AdbCommands` class when the connection attempt fails."""
def ConnectDevice(
self, *args, **kwargs
): # pylint: disable=invalid-name, no-self-use
"""Fail to connect to a device."""
raise socket_error
return None
class ClientFakeSuccess:
@ -85,31 +75,39 @@ class DeviceFake:
def patch_connect(success):
"""Mock the `adb.adb_commands.AdbCommands` and `adb_messenger.client.Client` classes."""
"""Mock the `adb_shell.adb_device.AdbDevice` and `adb_messenger.client.Client` classes."""
def connect_success_python(self, *args, **kwargs):
"""Mock the `AdbDeviceFake.connect` method when it succeeds."""
self.available = True
def connect_fail_python(self, *args, **kwargs):
"""Mock the `AdbDeviceFake.connect` method when it fails."""
raise socket_error
if success:
return {
"python": patch(
"androidtv.adb_manager.AdbCommands", AdbCommandsFakeSuccess
f"{__name__}.AdbDeviceFake.connect", connect_success_python
),
"server": patch("androidtv.adb_manager.Client", ClientFakeSuccess),
}
return {
"python": patch("androidtv.adb_manager.AdbCommands", AdbCommandsFakeFail),
"python": patch(f"{__name__}.AdbDeviceFake.connect", connect_fail_python),
"server": patch("androidtv.adb_manager.Client", ClientFakeFail),
}
def patch_shell(response=None, error=False):
"""Mock the `AdbCommandsFake.Shell` and `DeviceFake.shell` methods."""
"""Mock the `AdbDeviceFake.shell` and `DeviceFake.shell` methods."""
def shell_success(self, cmd):
"""Mock the `AdbCommandsFake.Shell` and `DeviceFake.shell` methods when they are successful."""
"""Mock the `AdbDeviceFake.shell` and `DeviceFake.shell` methods when they are successful."""
self.shell_cmd = cmd
return response
def shell_fail_python(self, cmd):
"""Mock the `AdbCommandsFake.Shell` method when it fails."""
"""Mock the `AdbDeviceFake.shell` method when it fails."""
self.shell_cmd = cmd
raise AttributeError
@ -120,10 +118,13 @@ def patch_shell(response=None, error=False):
if not error:
return {
"python": patch(f"{__name__}.AdbCommandsFake.Shell", shell_success),
"python": patch(f"{__name__}.AdbDeviceFake.shell", shell_success),
"server": patch(f"{__name__}.DeviceFake.shell", shell_success),
}
return {
"python": patch(f"{__name__}.AdbCommandsFake.Shell", shell_fail_python),
"python": patch(f"{__name__}.AdbDeviceFake.shell", shell_fail_python),
"server": patch(f"{__name__}.DeviceFake.shell", shell_fail_server),
}
PATCH_ADB_DEVICE = patch("androidtv.adb_manager.AdbDevice", AdbDeviceFake)

View file

@ -79,7 +79,9 @@ async def _test_reconnect(hass, caplog, config):
else:
entity_id = "media_player.fire_tv"
with patchers.patch_connect(True)[patch_key], patchers.patch_shell("")[patch_key]:
with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[
patch_key
], patchers.patch_shell("")[patch_key]:
assert await async_setup_component(hass, DOMAIN, config)
await hass.helpers.entity_component.async_update_entity(entity_id)
state = hass.states.get(entity_id)
@ -151,7 +153,9 @@ async def _test_adb_shell_returns_none(hass, config):
else:
entity_id = "media_player.fire_tv"
with patchers.patch_connect(True)[patch_key], patchers.patch_shell("")[patch_key]:
with patchers.PATCH_ADB_DEVICE, patchers.patch_connect(True)[
patch_key
], patchers.patch_shell("")[patch_key]:
assert await async_setup_component(hass, DOMAIN, config)
await hass.helpers.entity_component.async_update_entity(entity_id)
state = hass.states.get(entity_id)