Improve lupusec code quality (#109727)
* renamed async_add_devices * fixed typo * patch class instead of __init__ * ensure non blocking get_alarm * exception handling * added test case for json decode error * avoid blockign calls --------- Co-authored-by: suaveolent <suaveolent@users.noreply.github.com>
This commit is contained in:
parent
965f31a9e0
commit
668d036f71
7 changed files with 32 additions and 25 deletions
|
@ -1,4 +1,5 @@
|
||||||
"""Support for Lupusec Home Security system."""
|
"""Support for Lupusec Home Security system."""
|
||||||
|
from json import JSONDecodeError
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import lupupy
|
import lupupy
|
||||||
|
@ -111,16 +112,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
lupusec_system = await hass.async_add_executor_job(
|
lupusec_system = await hass.async_add_executor_job(
|
||||||
lupupy.Lupusec, username, password, host
|
lupupy.Lupusec, username, password, host
|
||||||
)
|
)
|
||||||
|
|
||||||
except LupusecException:
|
except LupusecException:
|
||||||
_LOGGER.error("Failed to connect to Lupusec device at %s", host)
|
_LOGGER.error("Failed to connect to Lupusec device at %s", host)
|
||||||
return False
|
return False
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except JSONDecodeError:
|
||||||
_LOGGER.error(
|
_LOGGER.error("Failed to connect to Lupusec device at %s", host)
|
||||||
"Unknown error while trying to connect to Lupusec device at %s: %s",
|
|
||||||
host,
|
|
||||||
ex,
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = lupusec_system
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = lupusec_system
|
||||||
|
|
|
@ -29,14 +29,14 @@ SCAN_INTERVAL = timedelta(seconds=2)
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_devices: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up an alarm control panel for a Lupusec device."""
|
"""Set up an alarm control panel for a Lupusec device."""
|
||||||
data = hass.data[DOMAIN][config_entry.entry_id]
|
data = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
alarm_devices = [LupusecAlarm(data, data.get_alarm(), config_entry.entry_id)]
|
alarm = await hass.async_add_executor_job(data.get_alarm)
|
||||||
|
|
||||||
async_add_devices(alarm_devices)
|
async_add_entities([LupusecAlarm(data, alarm, config_entry.entry_id)])
|
||||||
|
|
||||||
|
|
||||||
class LupusecAlarm(LupusecDevice, AlarmControlPanelEntity):
|
class LupusecAlarm(LupusecDevice, AlarmControlPanelEntity):
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from functools import partial
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import lupupy.constants as CONST
|
import lupupy.constants as CONST
|
||||||
|
@ -25,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_devices: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up a binary sensors for a Lupusec device."""
|
"""Set up a binary sensors for a Lupusec device."""
|
||||||
|
|
||||||
|
@ -34,10 +35,12 @@ async def async_setup_entry(
|
||||||
device_types = CONST.TYPE_OPENING + CONST.TYPE_SENSOR
|
device_types = CONST.TYPE_OPENING + CONST.TYPE_SENSOR
|
||||||
|
|
||||||
sensors = []
|
sensors = []
|
||||||
for device in data.get_devices(generic_type=device_types):
|
partial_func = partial(data.get_devices, generic_type=device_types)
|
||||||
|
devices = await hass.async_add_executor_job(partial_func)
|
||||||
|
for device in devices:
|
||||||
sensors.append(LupusecBinarySensor(device, config_entry.entry_id))
|
sensors.append(LupusecBinarySensor(device, config_entry.entry_id))
|
||||||
|
|
||||||
async_add_devices(sensors)
|
async_add_entities(sensors)
|
||||||
|
|
||||||
|
|
||||||
class LupusecBinarySensor(LupusecBaseSensor, BinarySensorEntity):
|
class LupusecBinarySensor(LupusecBaseSensor, BinarySensorEntity):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
""""Config flow for Lupusec integration."""
|
""""Config flow for Lupusec integration."""
|
||||||
|
|
||||||
|
from json import JSONDecodeError
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
@ -50,6 +51,8 @@ class LupusecConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
await test_host_connection(self.hass, host, username, password)
|
await test_host_connection(self.hass, host, username, password)
|
||||||
except CannotConnect:
|
except CannotConnect:
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
|
except JSONDecodeError:
|
||||||
|
errors["base"] = "cannot_connect"
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception("Unexpected exception")
|
_LOGGER.exception("Unexpected exception")
|
||||||
errors["base"] = "unknown"
|
errors["base"] = "unknown"
|
||||||
|
@ -80,6 +83,8 @@ class LupusecConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
await test_host_connection(self.hass, host, username, password)
|
await test_host_connection(self.hass, host, username, password)
|
||||||
except CannotConnect:
|
except CannotConnect:
|
||||||
return self.async_abort(reason="cannot_connect")
|
return self.async_abort(reason="cannot_connect")
|
||||||
|
except JSONDecodeError:
|
||||||
|
return self.async_abort(reason="cannot_connect")
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception("Unexpected exception")
|
_LOGGER.exception("Unexpected exception")
|
||||||
return self.async_abort(reason="unknown")
|
return self.async_abort(reason="unknown")
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"issues": {
|
"issues": {
|
||||||
"deprecated_yaml_import_issue_cannot_connect": {
|
"deprecated_yaml_import_issue_cannot_connect": {
|
||||||
"title": "The Lupus Electronics LUPUSEC YAML configuration import failed",
|
"title": "The Lupus Electronics LUPUSEC YAML configuration import failed",
|
||||||
"description": "Configuring Lupus Electronics LUPUSEC using YAML is being removed but there was an connection error importing your YAML configuration.\n\nEnsure connection to Lupus Electronics LUPUSEC works and restart Home Assistant to try again or remove the Lupus Electronics LUPUSEC YAML configuration from your configuration.yaml file and continue to [set up the integration]({url}) manually."
|
"description": "Configuring Lupus Electronics LUPUSEC using YAML is being removed but there was a connection error importing your YAML configuration.\n\nEnsure connection to Lupus Electronics LUPUSEC works and restart Home Assistant to try again or remove the Lupus Electronics LUPUSEC YAML configuration from your configuration.yaml file and continue to [set up the integration]({url}) manually."
|
||||||
},
|
},
|
||||||
"deprecated_yaml_import_issue_unknown": {
|
"deprecated_yaml_import_issue_unknown": {
|
||||||
"title": "The Lupus Electronics LUPUSEC YAML configuration import failed",
|
"title": "The Lupus Electronics LUPUSEC YAML configuration import failed",
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from functools import partial
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import lupupy.constants as CONST
|
import lupupy.constants as CONST
|
||||||
|
@ -20,7 +21,7 @@ SCAN_INTERVAL = timedelta(seconds=2)
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_devices: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Lupusec switch devices."""
|
"""Set up Lupusec switch devices."""
|
||||||
|
|
||||||
|
@ -29,10 +30,12 @@ async def async_setup_entry(
|
||||||
device_types = CONST.TYPE_SWITCH
|
device_types = CONST.TYPE_SWITCH
|
||||||
|
|
||||||
switches = []
|
switches = []
|
||||||
for device in data.get_devices(generic_type=device_types):
|
partial_func = partial(data.get_devices, generic_type=device_types)
|
||||||
|
devices = await hass.async_add_executor_job(partial_func)
|
||||||
|
for device in devices:
|
||||||
switches.append(LupusecSwitch(device, config_entry.entry_id))
|
switches.append(LupusecSwitch(device, config_entry.entry_id))
|
||||||
|
|
||||||
async_add_devices(switches)
|
async_add_entities(switches)
|
||||||
|
|
||||||
|
|
||||||
class LupusecSwitch(LupusecBaseSensor, SwitchEntity):
|
class LupusecSwitch(LupusecBaseSensor, SwitchEntity):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
""""Unit tests for the Lupusec config flow."""
|
""""Unit tests for the Lupusec config flow."""
|
||||||
|
|
||||||
|
from json import JSONDecodeError
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from lupupy import LupusecException
|
from lupupy import LupusecException
|
||||||
|
@ -51,8 +52,7 @@ async def test_form_valid_input(hass: HomeAssistant) -> None:
|
||||||
"homeassistant.components.lupusec.async_setup_entry",
|
"homeassistant.components.lupusec.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
) as mock_setup_entry, patch(
|
) as mock_setup_entry, patch(
|
||||||
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec.__init__",
|
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec",
|
||||||
return_value=None,
|
|
||||||
) as mock_initialize_lupusec:
|
) as mock_initialize_lupusec:
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
@ -71,6 +71,7 @@ async def test_form_valid_input(hass: HomeAssistant) -> None:
|
||||||
("raise_error", "text_error"),
|
("raise_error", "text_error"),
|
||||||
[
|
[
|
||||||
(LupusecException("Test lupusec exception"), "cannot_connect"),
|
(LupusecException("Test lupusec exception"), "cannot_connect"),
|
||||||
|
(JSONDecodeError("Test JSONDecodeError", "test", 1), "cannot_connect"),
|
||||||
(Exception("Test unknown exception"), "unknown"),
|
(Exception("Test unknown exception"), "unknown"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -85,7 +86,7 @@ async def test_flow_user_init_data_error_and_recover(
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec.__init__",
|
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec",
|
||||||
side_effect=raise_error,
|
side_effect=raise_error,
|
||||||
) as mock_initialize_lupusec:
|
) as mock_initialize_lupusec:
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
@ -104,8 +105,7 @@ async def test_flow_user_init_data_error_and_recover(
|
||||||
"homeassistant.components.lupusec.async_setup_entry",
|
"homeassistant.components.lupusec.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
) as mock_setup_entry, patch(
|
) as mock_setup_entry, patch(
|
||||||
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec.__init__",
|
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec",
|
||||||
return_value=None,
|
|
||||||
) as mock_initialize_lupusec:
|
) as mock_initialize_lupusec:
|
||||||
result3 = await hass.config_entries.flow.async_configure(
|
result3 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
@ -164,8 +164,7 @@ async def test_flow_source_import(
|
||||||
"homeassistant.components.lupusec.async_setup_entry",
|
"homeassistant.components.lupusec.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
) as mock_setup_entry, patch(
|
) as mock_setup_entry, patch(
|
||||||
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec.__init__",
|
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec",
|
||||||
return_value=None,
|
|
||||||
) as mock_initialize_lupusec:
|
) as mock_initialize_lupusec:
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -186,6 +185,7 @@ async def test_flow_source_import(
|
||||||
("raise_error", "text_error"),
|
("raise_error", "text_error"),
|
||||||
[
|
[
|
||||||
(LupusecException("Test lupusec exception"), "cannot_connect"),
|
(LupusecException("Test lupusec exception"), "cannot_connect"),
|
||||||
|
(JSONDecodeError("Test JSONDecodeError", "test", 1), "cannot_connect"),
|
||||||
(Exception("Test unknown exception"), "unknown"),
|
(Exception("Test unknown exception"), "unknown"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -195,7 +195,7 @@ async def test_flow_source_import_error_and_recover(
|
||||||
"""Test exceptions and recovery."""
|
"""Test exceptions and recovery."""
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec.__init__",
|
"homeassistant.components.lupusec.config_flow.lupupy.Lupusec",
|
||||||
side_effect=raise_error,
|
side_effect=raise_error,
|
||||||
) as mock_initialize_lupusec:
|
) as mock_initialize_lupusec:
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue