Version sensor entity cleanup (#53915)
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
25f3cdde50
commit
d80da944a3
2 changed files with 98 additions and 75 deletions
|
@ -2,11 +2,19 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pyhaversion import HaVersion, HaVersionChannel, HaVersionSource
|
from pyhaversion import (
|
||||||
from pyhaversion.exceptions import HaVersionFetchException, HaVersionParseException
|
HaVersion,
|
||||||
|
HaVersionChannel,
|
||||||
|
HaVersionSource,
|
||||||
|
exceptions as pyhaversionexceptions,
|
||||||
|
)
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
from homeassistant.components.sensor import (
|
||||||
|
PLATFORM_SCHEMA,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.const import CONF_NAME, CONF_SOURCE
|
from homeassistant.const import CONF_NAME, CONF_SOURCE
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
@ -30,12 +38,10 @@ ALL_IMAGES = [
|
||||||
"raspberrypi4",
|
"raspberrypi4",
|
||||||
"tinker",
|
"tinker",
|
||||||
]
|
]
|
||||||
ALL_SOURCES = [
|
|
||||||
"container",
|
HA_VERSION_SOURCES = [source.value for source in HaVersionSource]
|
||||||
"haio",
|
|
||||||
"local",
|
ALL_SOURCES = HA_VERSION_SOURCES + [
|
||||||
"pypi",
|
|
||||||
"supervisor",
|
|
||||||
"hassio", # Kept to not break existing configurations
|
"hassio", # Kept to not break existing configurations
|
||||||
"docker", # Kept to not break existing configurations
|
"docker", # Kept to not break existing configurations
|
||||||
]
|
]
|
||||||
|
@ -48,8 +54,6 @@ DEFAULT_NAME_LATEST = "Latest Version"
|
||||||
DEFAULT_NAME_LOCAL = "Current Version"
|
DEFAULT_NAME_LOCAL = "Current Version"
|
||||||
DEFAULT_SOURCE = "local"
|
DEFAULT_SOURCE = "local"
|
||||||
|
|
||||||
ICON = "mdi:package-up"
|
|
||||||
|
|
||||||
TIME_BETWEEN_UPDATES = timedelta(minutes=5)
|
TIME_BETWEEN_UPDATES = timedelta(minutes=5)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
@ -72,40 +76,42 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
source = config.get(CONF_SOURCE)
|
source = config.get(CONF_SOURCE)
|
||||||
|
|
||||||
|
channel = HaVersionChannel.BETA if beta else HaVersionChannel.STABLE
|
||||||
session = async_get_clientsession(hass)
|
session = async_get_clientsession(hass)
|
||||||
|
|
||||||
channel = HaVersionChannel.BETA if beta else HaVersionChannel.STABLE
|
if source in HA_VERSION_SOURCES:
|
||||||
|
source = HaVersionSource(source)
|
||||||
|
elif source == "hassio":
|
||||||
|
source = HaVersionSource.SUPERVISOR
|
||||||
|
elif source == "docker":
|
||||||
|
source = HaVersionSource.CONTAINER
|
||||||
|
|
||||||
if source == "pypi":
|
if (
|
||||||
haversion = VersionData(
|
source in (HaVersionSource.SUPERVISOR, HaVersionSource.CONTAINER)
|
||||||
HaVersion(session, source=HaVersionSource.PYPI, channel=channel)
|
and image is not None
|
||||||
)
|
and image != DEFAULT_IMAGE
|
||||||
elif source in ["hassio", "supervisor"]:
|
):
|
||||||
haversion = VersionData(
|
|
||||||
HaVersion(
|
|
||||||
session, source=HaVersionSource.SUPERVISOR, channel=channel, image=image
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif source in ["docker", "container"]:
|
|
||||||
if image is not None and image != DEFAULT_IMAGE:
|
|
||||||
image = f"{image}-homeassistant"
|
image = f"{image}-homeassistant"
|
||||||
haversion = VersionData(
|
|
||||||
HaVersion(
|
|
||||||
session, source=HaVersionSource.CONTAINER, channel=channel, image=image
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif source == "haio":
|
|
||||||
haversion = VersionData(HaVersion(session, source=HaVersionSource.HAIO))
|
|
||||||
else:
|
|
||||||
haversion = VersionData(HaVersion(session, source=HaVersionSource.LOCAL))
|
|
||||||
|
|
||||||
if not name:
|
if not (name := config.get(CONF_NAME)):
|
||||||
if source == DEFAULT_SOURCE:
|
if source == HaVersionSource.LOCAL:
|
||||||
name = DEFAULT_NAME_LOCAL
|
name = DEFAULT_NAME_LOCAL
|
||||||
else:
|
else:
|
||||||
name = DEFAULT_NAME_LATEST
|
name = DEFAULT_NAME_LATEST
|
||||||
|
|
||||||
async_add_entities([VersionSensor(haversion, name)], True)
|
async_add_entities(
|
||||||
|
[
|
||||||
|
VersionSensor(
|
||||||
|
VersionData(
|
||||||
|
HaVersion(
|
||||||
|
session=session, source=source, image=image, channel=channel
|
||||||
|
)
|
||||||
|
),
|
||||||
|
SensorEntityDescription(key=source, name=name),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VersionData:
|
class VersionData:
|
||||||
|
@ -120,9 +126,9 @@ class VersionData:
|
||||||
"""Get the latest version information."""
|
"""Get the latest version information."""
|
||||||
try:
|
try:
|
||||||
await self.api.get_version()
|
await self.api.get_version()
|
||||||
except HaVersionFetchException as exception:
|
except pyhaversionexceptions.HaVersionFetchException as exception:
|
||||||
_LOGGER.warning(exception)
|
_LOGGER.warning(exception)
|
||||||
except HaVersionParseException as exception:
|
except pyhaversionexceptions.HaVersionParseException as exception:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Could not parse data received for %s - %s", self.api.source, exception
|
"Could not parse data received for %s - %s", self.api.source, exception
|
||||||
)
|
)
|
||||||
|
@ -131,32 +137,19 @@ class VersionData:
|
||||||
class VersionSensor(SensorEntity):
|
class VersionSensor(SensorEntity):
|
||||||
"""Representation of a Home Assistant version sensor."""
|
"""Representation of a Home Assistant version sensor."""
|
||||||
|
|
||||||
def __init__(self, data: VersionData, name: str) -> None:
|
_attr_icon = "mdi:package-up"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
data: VersionData,
|
||||||
|
description: SensorEntityDescription,
|
||||||
|
) -> None:
|
||||||
"""Initialize the Version sensor."""
|
"""Initialize the Version sensor."""
|
||||||
self.data = data
|
self.data = data
|
||||||
self._name = name
|
self.entity_description = description
|
||||||
self._state = None
|
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Get the latest version information."""
|
"""Get the latest version information."""
|
||||||
await self.data.async_update()
|
await self.data.async_update()
|
||||||
|
self._attr_state = self.data.api.version
|
||||||
@property
|
self._attr_extra_state_attributes = self.data.api.version_data
|
||||||
def name(self):
|
|
||||||
"""Return the name of the sensor."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self):
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
return self.data.api.version
|
|
||||||
|
|
||||||
@property
|
|
||||||
def extra_state_attributes(self):
|
|
||||||
"""Return attributes for the sensor."""
|
|
||||||
return self.data.api.version_data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Return the icon to use in the frontend, if any."""
|
|
||||||
return ICON
|
|
||||||
|
|
|
@ -1,26 +1,56 @@
|
||||||
"""The test for the version sensor platform."""
|
"""The test for the version sensor platform."""
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from pyhaversion import HaVersionSource, exceptions as pyhaversionexceptions
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.version.sensor import ALL_SOURCES
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
MOCK_VERSION = "10.0"
|
MOCK_VERSION = "10.0"
|
||||||
|
|
||||||
|
|
||||||
async def test_version_sensor(hass):
|
@pytest.mark.parametrize(
|
||||||
"""Test the Version sensor."""
|
"source",
|
||||||
config = {"sensor": {"platform": "version"}}
|
ALL_SOURCES,
|
||||||
|
)
|
||||||
|
async def test_version_source(hass, source):
|
||||||
|
"""Test the Version sensor with different sources."""
|
||||||
|
config = {
|
||||||
|
"sensor": {"platform": "version", "source": source, "image": "qemux86-64"}
|
||||||
|
}
|
||||||
|
|
||||||
assert await async_setup_component(hass, "sensor", config)
|
with patch("pyhaversion.version.HaVersion.version", MOCK_VERSION):
|
||||||
|
|
||||||
|
|
||||||
async def test_version(hass):
|
|
||||||
"""Test the Version sensor."""
|
|
||||||
config = {"sensor": {"platform": "version", "name": "test"}}
|
|
||||||
|
|
||||||
with patch("homeassistant.const.__version__", MOCK_VERSION):
|
|
||||||
assert await async_setup_component(hass, "sensor", config)
|
assert await async_setup_component(hass, "sensor", config)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get("sensor.test")
|
name = "current_version" if source == HaVersionSource.LOCAL else "latest_version"
|
||||||
|
state = hass.states.get(f"sensor.{name}")
|
||||||
|
|
||||||
assert state.state == "10.0"
|
assert state.state == MOCK_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
async def test_version_fetch_exception(hass, caplog):
|
||||||
|
"""Test fetch exception thrown during updates."""
|
||||||
|
config = {"sensor": {"platform": "version"}}
|
||||||
|
with patch(
|
||||||
|
"pyhaversion.version.HaVersion.get_version",
|
||||||
|
side_effect=pyhaversionexceptions.HaVersionFetchException(
|
||||||
|
"Fetch exception from pyhaversion"
|
||||||
|
),
|
||||||
|
):
|
||||||
|
assert await async_setup_component(hass, "sensor", config)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert "Fetch exception from pyhaversion" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_version_parse_exception(hass, caplog):
|
||||||
|
"""Test parse exception thrown during updates."""
|
||||||
|
config = {"sensor": {"platform": "version"}}
|
||||||
|
with patch(
|
||||||
|
"pyhaversion.version.HaVersion.get_version",
|
||||||
|
side_effect=pyhaversionexceptions.HaVersionParseException,
|
||||||
|
):
|
||||||
|
assert await async_setup_component(hass, "sensor", config)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert "Could not parse data received for HaVersionSource.LOCAL" in caplog.text
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue