Bump pyuptimerobot to 21.8.1 (#53995)
* Bump pyuptimerobot to 21.08.0 * pylint * bump to 21.8.1 * Uppdate strings * Update homeassistant/components/uptimerobot/strings.json Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
1bc3c743db
commit
4a37ff2dda
11 changed files with 73 additions and 102 deletions
|
@ -1,44 +1,35 @@
|
||||||
"""The Uptime Robot integration."""
|
"""The Uptime Robot integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import async_timeout
|
from pyuptimerobot import UptimeRobot, UptimeRobotException, UptimeRobotMonitor
|
||||||
from pyuptimerobot import UptimeRobot
|
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY
|
from homeassistant.const import CONF_API_KEY
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import (
|
from .const import API_ATTR_OK, COORDINATOR_UPDATE_INTERVAL, DOMAIN, LOGGER, PLATFORMS
|
||||||
API_ATTR_MONITORS,
|
|
||||||
API_ATTR_OK,
|
|
||||||
API_ATTR_STAT,
|
|
||||||
CONNECTION_ERROR,
|
|
||||||
COORDINATOR_UPDATE_INTERVAL,
|
|
||||||
DOMAIN,
|
|
||||||
LOGGER,
|
|
||||||
PLATFORMS,
|
|
||||||
MonitorData,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up Uptime Robot from a config entry."""
|
"""Set up Uptime Robot from a config entry."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
uptime_robot_api = UptimeRobot()
|
uptime_robot_api = UptimeRobot(
|
||||||
|
entry.data[CONF_API_KEY], async_get_clientsession(hass)
|
||||||
|
)
|
||||||
|
|
||||||
async def async_update_data() -> list[MonitorData]:
|
async def async_update_data() -> list[UptimeRobotMonitor]:
|
||||||
"""Fetch data from API UptimeRobot API."""
|
"""Fetch data from API UptimeRobot API."""
|
||||||
async with async_timeout.timeout(10):
|
try:
|
||||||
monitors = await hass.async_add_executor_job(
|
response = await uptime_robot_api.async_get_monitors()
|
||||||
uptime_robot_api.getMonitors, entry.data[CONF_API_KEY]
|
except UptimeRobotException as exception:
|
||||||
)
|
raise UpdateFailed(exception) from exception
|
||||||
if not monitors or monitors.get(API_ATTR_STAT) != API_ATTR_OK:
|
else:
|
||||||
raise UpdateFailed(CONNECTION_ERROR)
|
if response.status == API_ATTR_OK:
|
||||||
return [
|
monitors: list[UptimeRobotMonitor] = response.data
|
||||||
MonitorData.from_dict(monitor)
|
return monitors
|
||||||
for monitor in monitors.get(API_ATTR_MONITORS, [])
|
raise UpdateFailed(response.error.message)
|
||||||
]
|
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = coordinator = DataUpdateCoordinator(
|
hass.data[DOMAIN][entry.entry_id] = coordinator = DataUpdateCoordinator(
|
||||||
hass,
|
hass,
|
||||||
|
|
|
@ -50,7 +50,7 @@ async def async_setup_entry(
|
||||||
coordinator,
|
coordinator,
|
||||||
BinarySensorEntityDescription(
|
BinarySensorEntityDescription(
|
||||||
key=str(monitor.id),
|
key=str(monitor.id),
|
||||||
name=monitor.name,
|
name=monitor.friendly_name,
|
||||||
device_class=DEVICE_CLASS_CONNECTIVITY,
|
device_class=DEVICE_CLASS_CONNECTIVITY,
|
||||||
),
|
),
|
||||||
target=monitor.url,
|
target=monitor.url,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Config flow for Uptime Robot integration."""
|
"""Config flow for Uptime Robot integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pyuptimerobot import UptimeRobot
|
from pyuptimerobot import UptimeRobot, UptimeRobotAccount, UptimeRobotException
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
|
@ -9,24 +9,26 @@ from homeassistant.const import CONF_API_KEY
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import API_ATTR_OK, API_ATTR_STAT, DOMAIN, LOGGER
|
from .const import API_ATTR_OK, DOMAIN, LOGGER
|
||||||
|
|
||||||
STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_API_KEY): str})
|
STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_API_KEY): str})
|
||||||
|
|
||||||
|
|
||||||
async def validate_input(hass: HomeAssistant, data: ConfigType) -> None:
|
async def validate_input(hass: HomeAssistant, data: ConfigType) -> UptimeRobotAccount:
|
||||||
"""Validate the user input allows us to connect."""
|
"""Validate the user input allows us to connect."""
|
||||||
|
uptime_robot_api = UptimeRobot(data[CONF_API_KEY], async_get_clientsession(hass))
|
||||||
|
|
||||||
uptime_robot_api = UptimeRobot()
|
try:
|
||||||
|
response = await uptime_robot_api.async_get_account_details()
|
||||||
monitors = await hass.async_add_executor_job(
|
except UptimeRobotException as exception:
|
||||||
uptime_robot_api.getMonitors, data[CONF_API_KEY]
|
raise CannotConnect(exception) from exception
|
||||||
)
|
else:
|
||||||
|
if response.status == API_ATTR_OK:
|
||||||
if not monitors or monitors.get(API_ATTR_STAT) != API_ATTR_OK:
|
return response.data
|
||||||
raise CannotConnect("Error communicating with Uptime Robot API")
|
raise CannotConnect(response.error.message)
|
||||||
|
|
||||||
|
|
||||||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
@ -43,14 +45,14 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await validate_input(self.hass, user_input)
|
account = await validate_input(self.hass, user_input)
|
||||||
except CannotConnect:
|
except CannotConnect:
|
||||||
errors["base"] = "cannot_connect"
|
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"
|
||||||
else:
|
else:
|
||||||
return self.async_create_entry(title="", data=user_input)
|
return self.async_create_entry(title=account.email, data=user_input)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
|
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
|
||||||
|
@ -65,9 +67,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
)
|
)
|
||||||
return self.async_abort(reason="already_configured")
|
return self.async_abort(reason="already_configured")
|
||||||
|
|
||||||
return self.async_create_entry(
|
imported_config = {CONF_API_KEY: import_config[CONF_API_KEY]}
|
||||||
title="", data={CONF_API_KEY: import_config[CONF_API_KEY]}
|
|
||||||
)
|
account = await validate_input(self.hass, imported_config)
|
||||||
|
return self.async_create_entry(title=account.email, data=imported_config)
|
||||||
|
|
||||||
|
|
||||||
class CannotConnect(HomeAssistantError):
|
class CannotConnect(HomeAssistantError):
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
"""Constants for the Uptime Robot integration."""
|
"""Constants for the Uptime Robot integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from enum import Enum
|
|
||||||
from logging import Logger, getLogger
|
from logging import Logger, getLogger
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
|
@ -14,42 +12,8 @@ COORDINATOR_UPDATE_INTERVAL: timedelta = timedelta(seconds=60)
|
||||||
DOMAIN: Final = "uptimerobot"
|
DOMAIN: Final = "uptimerobot"
|
||||||
PLATFORMS: Final = ["binary_sensor"]
|
PLATFORMS: Final = ["binary_sensor"]
|
||||||
|
|
||||||
CONNECTION_ERROR: Final = "Error connecting to the Uptime Robot API"
|
|
||||||
|
|
||||||
ATTRIBUTION: Final = "Data provided by Uptime Robot"
|
ATTRIBUTION: Final = "Data provided by Uptime Robot"
|
||||||
|
|
||||||
ATTR_TARGET: Final = "target"
|
ATTR_TARGET: Final = "target"
|
||||||
|
|
||||||
API_ATTR_STAT: Final = "stat"
|
|
||||||
API_ATTR_OK: Final = "ok"
|
API_ATTR_OK: Final = "ok"
|
||||||
API_ATTR_MONITORS: Final = "monitors"
|
|
||||||
|
|
||||||
|
|
||||||
class MonitorType(Enum):
|
|
||||||
"""Monitors type."""
|
|
||||||
|
|
||||||
HTTP = 1
|
|
||||||
keyword = 2
|
|
||||||
ping = 3
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MonitorData:
|
|
||||||
"""Dataclass for monitors."""
|
|
||||||
|
|
||||||
id: int
|
|
||||||
status: int
|
|
||||||
url: str
|
|
||||||
name: str
|
|
||||||
type: MonitorType
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_dict(monitor: dict) -> MonitorData:
|
|
||||||
"""Create a new monitor from a dict."""
|
|
||||||
return MonitorData(
|
|
||||||
id=monitor["id"],
|
|
||||||
status=monitor["status"],
|
|
||||||
url=monitor["url"],
|
|
||||||
name=monitor["friendly_name"],
|
|
||||||
type=MonitorType(monitor["type"]),
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""Base UptimeRobot entity."""
|
"""Base UptimeRobot entity."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pyuptimerobot import UptimeRobotMonitor
|
||||||
|
|
||||||
from homeassistant.const import ATTR_ATTRIBUTION
|
from homeassistant.const import ATTR_ATTRIBUTION
|
||||||
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
|
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
|
||||||
from homeassistant.helpers.update_coordinator import (
|
from homeassistant.helpers.update_coordinator import (
|
||||||
|
@ -8,7 +10,7 @@ from homeassistant.helpers.update_coordinator import (
|
||||||
DataUpdateCoordinator,
|
DataUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .const import ATTR_TARGET, ATTRIBUTION, DOMAIN, MonitorData
|
from .const import ATTR_TARGET, ATTRIBUTION, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
class UptimeRobotEntity(CoordinatorEntity):
|
class UptimeRobotEntity(CoordinatorEntity):
|
||||||
|
@ -48,12 +50,12 @@ class UptimeRobotEntity(CoordinatorEntity):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def monitors(self) -> list[MonitorData]:
|
def monitors(self) -> list[UptimeRobotMonitor]:
|
||||||
"""Return all monitors."""
|
"""Return all monitors."""
|
||||||
return self.coordinator.data or []
|
return self.coordinator.data or []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def monitor(self) -> MonitorData | None:
|
def monitor(self) -> UptimeRobotMonitor | None:
|
||||||
"""Return the monitor for this entity."""
|
"""Return the monitor for this entity."""
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
|
@ -67,7 +69,8 @@ class UptimeRobotEntity(CoordinatorEntity):
|
||||||
@property
|
@property
|
||||||
def monitor_available(self) -> bool:
|
def monitor_available(self) -> bool:
|
||||||
"""Returtn if the monitor is available."""
|
"""Returtn if the monitor is available."""
|
||||||
return self.monitor.status == 2 if self.monitor else False
|
status: bool = self.monitor.status == 2 if self.monitor else False
|
||||||
|
return status
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self) -> bool:
|
def available(self) -> bool:
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Uptime Robot",
|
"name": "Uptime Robot",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/uptimerobot",
|
"documentation": "https://www.home-assistant.io/integrations/uptimerobot",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyuptimerobot==0.0.5"
|
"pyuptimerobot==21.8.1"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@ludeeus"
|
"@ludeeus"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "Device is already configured"
|
"already_configured": "Account already configured"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "Failed to connect",
|
"cannot_connect": "Failed to connect",
|
||||||
|
|
|
@ -1948,7 +1948,7 @@ pytradfri[async]==7.0.6
|
||||||
pytrafikverket==0.1.6.2
|
pytrafikverket==0.1.6.2
|
||||||
|
|
||||||
# homeassistant.components.uptimerobot
|
# homeassistant.components.uptimerobot
|
||||||
pyuptimerobot==0.0.5
|
pyuptimerobot==21.8.1
|
||||||
|
|
||||||
# homeassistant.components.keyboard
|
# homeassistant.components.keyboard
|
||||||
# pyuserinput==0.1.11
|
# pyuserinput==0.1.11
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ pytraccar==0.9.0
|
||||||
pytradfri[async]==7.0.6
|
pytradfri[async]==7.0.6
|
||||||
|
|
||||||
# homeassistant.components.uptimerobot
|
# homeassistant.components.uptimerobot
|
||||||
pyuptimerobot==0.0.5
|
pyuptimerobot==21.8.1
|
||||||
|
|
||||||
# homeassistant.components.vera
|
# homeassistant.components.vera
|
||||||
pyvera==0.3.13
|
pyvera==0.3.13
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
"""Test the Uptime Robot config flow."""
|
"""Test the Uptime Robot config flow."""
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from pyuptimerobot import UptimeRobotApiResponse
|
||||||
|
|
||||||
from homeassistant import config_entries, setup
|
from homeassistant import config_entries, setup
|
||||||
from homeassistant.components.uptimerobot.const import (
|
from homeassistant.components.uptimerobot.const import DOMAIN
|
||||||
API_ATTR_MONITORS,
|
|
||||||
API_ATTR_OK,
|
|
||||||
API_ATTR_STAT,
|
|
||||||
DOMAIN,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import (
|
from homeassistant.data_entry_flow import (
|
||||||
RESULT_TYPE_ABORT,
|
RESULT_TYPE_ABORT,
|
||||||
|
@ -26,8 +23,13 @@ async def test_form(hass: HomeAssistant) -> None:
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"pyuptimerobot.UptimeRobot.getMonitors",
|
"pyuptimerobot.UptimeRobot.async_get_account_details",
|
||||||
return_value={API_ATTR_STAT: API_ATTR_OK, API_ATTR_MONITORS: []},
|
return_value=UptimeRobotApiResponse.from_dict(
|
||||||
|
{
|
||||||
|
"stat": "ok",
|
||||||
|
"account": {"email": "test@test.test"},
|
||||||
|
}
|
||||||
|
),
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.uptimerobot.async_setup_entry",
|
"homeassistant.components.uptimerobot.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
|
@ -39,7 +41,7 @@ async def test_form(hass: HomeAssistant) -> None:
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result2["title"] == ""
|
assert result2["title"] == "test@test.test"
|
||||||
assert result2["data"] == {"api_key": "1234"}
|
assert result2["data"] == {"api_key": "1234"}
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
@ -50,7 +52,10 @@ async def test_form_cannot_connect(hass: HomeAssistant) -> None:
|
||||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch("pyuptimerobot.UptimeRobot.getMonitors", return_value=None):
|
with patch(
|
||||||
|
"pyuptimerobot.UptimeRobot.async_get_account_details",
|
||||||
|
return_value=UptimeRobotApiResponse.from_dict({"stat": "fail", "error": {}}),
|
||||||
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{"api_key": "1234"},
|
{"api_key": "1234"},
|
||||||
|
@ -63,8 +68,13 @@ async def test_form_cannot_connect(hass: HomeAssistant) -> None:
|
||||||
async def test_flow_import(hass):
|
async def test_flow_import(hass):
|
||||||
"""Test an import flow."""
|
"""Test an import flow."""
|
||||||
with patch(
|
with patch(
|
||||||
"pyuptimerobot.UptimeRobot.getMonitors",
|
"pyuptimerobot.UptimeRobot.async_get_account_details",
|
||||||
return_value={API_ATTR_STAT: API_ATTR_OK, API_ATTR_MONITORS: []},
|
return_value=UptimeRobotApiResponse.from_dict(
|
||||||
|
{
|
||||||
|
"stat": "ok",
|
||||||
|
"account": {"email": "test@test.test"},
|
||||||
|
}
|
||||||
|
),
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.uptimerobot.async_setup_entry",
|
"homeassistant.components.uptimerobot.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
|
@ -81,8 +91,8 @@ async def test_flow_import(hass):
|
||||||
assert result["data"] == {"api_key": "1234"}
|
assert result["data"] == {"api_key": "1234"}
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"pyuptimerobot.UptimeRobot.getMonitors",
|
"pyuptimerobot.UptimeRobot.async_get_account_details",
|
||||||
return_value={API_ATTR_STAT: API_ATTR_OK, API_ATTR_MONITORS: []},
|
return_value=UptimeRobotApiResponse.from_dict({"stat": "ok", "monitors": []}),
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.uptimerobot.async_setup_entry",
|
"homeassistant.components.uptimerobot.async_setup_entry",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue