Improve type hints in blebox (#80511)
* Add generics to blebox * Remove walrus * Move logic into each platform * Code style * Apply suggestion
This commit is contained in:
parent
6ea6782d23
commit
374d46ec09
8 changed files with 79 additions and 62 deletions
|
@ -1,5 +1,6 @@
|
|||
"""The BleBox devices integration."""
|
||||
import logging
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
from blebox_uniapi.error import Error
|
||||
|
@ -8,7 +9,7 @@ from blebox_uniapi.session import ApiHost
|
|||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||
|
@ -28,6 +29,8 @@ PLATFORMS = [
|
|||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
_FeatureT = TypeVar("_FeatureT", bound=Feature)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up BleBox devices from a config entry."""
|
||||
|
@ -64,26 +67,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
return unload_ok
|
||||
|
||||
|
||||
@callback
|
||||
def create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, entity_klass, entity_type
|
||||
):
|
||||
"""Create entities from a BleBox product's features."""
|
||||
|
||||
product = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
entities = []
|
||||
|
||||
if entity_type in product.features:
|
||||
for feature in product.features[entity_type]:
|
||||
entities.append(entity_klass(feature))
|
||||
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxEntity(Entity):
|
||||
class BleBoxEntity(Entity, Generic[_FeatureT]):
|
||||
"""Implements a common class for entities representing a BleBox feature."""
|
||||
|
||||
def __init__(self, feature: Feature) -> None:
|
||||
def __init__(self, feature: _FeatureT) -> None:
|
||||
"""Initialize a BleBox entity."""
|
||||
self._feature = feature
|
||||
self._attr_name = feature.full_name
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
"""BleBox button entities implementation."""
|
||||
from __future__ import annotations
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.button
|
||||
|
||||
from homeassistant.components.button import ButtonEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -15,20 +19,23 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox button entry."""
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxButtonEntity, "buttons"
|
||||
)
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
|
||||
entities = [
|
||||
BleBoxButtonEntity(feature) for feature in product.features.get("buttons", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxButtonEntity(BleBoxEntity, ButtonEntity):
|
||||
class BleBoxButtonEntity(BleBoxEntity[blebox_uniapi.button.Button], ButtonEntity):
|
||||
"""Representation of BleBox buttons."""
|
||||
|
||||
def __init__(self, feature):
|
||||
def __init__(self, feature: blebox_uniapi.button.Button) -> None:
|
||||
"""Initialize a BleBox button feature."""
|
||||
super().__init__(feature)
|
||||
self._attr_icon = self.get_icon()
|
||||
|
||||
def get_icon(self):
|
||||
def get_icon(self) -> str | None:
|
||||
"""Return icon for endpoint."""
|
||||
if "up" in self._feature.query_string:
|
||||
return "mdi:arrow-up-circle"
|
||||
|
@ -40,7 +47,7 @@ class BleBoxButtonEntity(BleBoxEntity, ButtonEntity):
|
|||
return "mdi:arrow-up-circle"
|
||||
if "close" in self._feature.query_string:
|
||||
return "mdi:arrow-down-circle"
|
||||
return ""
|
||||
return None
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Handle the button press."""
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.climate
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ClimateEntity,
|
||||
ClimateEntityFeature,
|
||||
|
@ -13,7 +16,8 @@ from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=5)
|
||||
|
||||
|
@ -24,13 +28,15 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox climate entity."""
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxClimateEntity, "climates"
|
||||
)
|
||||
entities = [
|
||||
BleBoxClimateEntity(feature) for feature in product.features.get("climates", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxClimateEntity(BleBoxEntity, ClimateEntity):
|
||||
class BleBoxClimateEntity(BleBoxEntity[blebox_uniapi.climate.Climate], ClimateEntity):
|
||||
"""Representation of a BleBox climate feature (saunaBox)."""
|
||||
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
|
|
|
@ -3,6 +3,9 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.cover
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
CoverDeviceClass,
|
||||
|
@ -14,7 +17,8 @@ from homeassistant.const import STATE_CLOSED, STATE_CLOSING, STATE_OPEN, STATE_O
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
BLEBOX_TO_COVER_DEVICE_CLASSES = {
|
||||
"gate": CoverDeviceClass.GATE,
|
||||
|
@ -44,16 +48,17 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox entry."""
|
||||
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxCoverEntity, "covers"
|
||||
)
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
entities = [
|
||||
BleBoxCoverEntity(feature) for feature in product.features.get("covers", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxCoverEntity(BleBoxEntity, CoverEntity):
|
||||
class BleBoxCoverEntity(BleBoxEntity[blebox_uniapi.cover.Cover], CoverEntity):
|
||||
"""Representation of a BleBox cover feature."""
|
||||
|
||||
def __init__(self, feature):
|
||||
def __init__(self, feature: blebox_uniapi.cover.Cover) -> None:
|
||||
"""Initialize a BleBox cover feature."""
|
||||
super().__init__(feature)
|
||||
self._attr_device_class = BLEBOX_TO_COVER_DEVICE_CLASSES[feature.device_class]
|
||||
|
|
|
@ -5,6 +5,7 @@ from datetime import timedelta
|
|||
import logging
|
||||
from typing import Any
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.light
|
||||
from blebox_uniapi.light import BleboxColorMode
|
||||
|
||||
|
@ -23,7 +24,8 @@ from homeassistant.config_entries import ConfigEntry
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -36,10 +38,11 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox entry."""
|
||||
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxLightEntity, "lights"
|
||||
)
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
entities = [
|
||||
BleBoxLightEntity(feature) for feature in product.features.get("lights", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
COLOR_MODE_MAP = {
|
||||
|
@ -53,11 +56,9 @@ COLOR_MODE_MAP = {
|
|||
}
|
||||
|
||||
|
||||
class BleBoxLightEntity(BleBoxEntity, LightEntity):
|
||||
class BleBoxLightEntity(BleBoxEntity[blebox_uniapi.light.Light], LightEntity):
|
||||
"""Representation of BleBox lights."""
|
||||
|
||||
_feature: blebox_uniapi.light.Light
|
||||
|
||||
def __init__(self, feature: blebox_uniapi.light.Light) -> None:
|
||||
"""Initialize a BleBox light."""
|
||||
super().__init__(feature)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
"""BleBox sensor entities."""
|
||||
from dataclasses import dataclass
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.sensor
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
|
@ -11,7 +14,8 @@ from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, TEMP_C
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -49,16 +53,17 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox entry."""
|
||||
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxSensorEntity, "sensors"
|
||||
)
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
entities = [
|
||||
BleBoxSensorEntity(feature) for feature in product.features.get("sensors", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxSensorEntity(BleBoxEntity, SensorEntity):
|
||||
class BleBoxSensorEntity(BleBoxEntity[blebox_uniapi.sensor.BaseSensor], SensorEntity):
|
||||
"""Representation of a BleBox sensor feature."""
|
||||
|
||||
def __init__(self, feature):
|
||||
def __init__(self, feature: blebox_uniapi.sensor.BaseSensor) -> None:
|
||||
"""Initialize a BleBox sensor feature."""
|
||||
super().__init__(feature)
|
||||
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from blebox_uniapi.box import Box
|
||||
import blebox_uniapi.switch
|
||||
|
||||
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BleBoxEntity, create_blebox_entities
|
||||
from . import BleBoxEntity
|
||||
from .const import DOMAIN, PRODUCT
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=5)
|
||||
|
||||
|
@ -18,15 +22,17 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up a BleBox switch entity."""
|
||||
create_blebox_entities(
|
||||
hass, config_entry, async_add_entities, BleBoxSwitchEntity, "switches"
|
||||
)
|
||||
product: Box = hass.data[DOMAIN][config_entry.entry_id][PRODUCT]
|
||||
entities = [
|
||||
BleBoxSwitchEntity(feature) for feature in product.features.get("switches", [])
|
||||
]
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class BleBoxSwitchEntity(BleBoxEntity, SwitchEntity):
|
||||
class BleBoxSwitchEntity(BleBoxEntity[blebox_uniapi.switch.Switch], SwitchEntity):
|
||||
"""Representation of a BleBox switch feature."""
|
||||
|
||||
def __init__(self, feature):
|
||||
def __init__(self, feature: blebox_uniapi.switch.Switch) -> None:
|
||||
"""Initialize a BleBox switch feature."""
|
||||
super().__init__(feature)
|
||||
self._attr_device_class = SwitchDeviceClass.SWITCH
|
||||
|
|
|
@ -7,7 +7,7 @@ import blebox_uniapi
|
|||
from homeassistant.components.blebox.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
|
||||
from .conftest import mock_config, patch_product_identify
|
||||
from .conftest import mock_config, patch_product_identify, setup_product_mock
|
||||
|
||||
|
||||
async def test_setup_failure(hass, caplog):
|
||||
|
@ -44,7 +44,7 @@ async def test_setup_failure_on_connection(hass, caplog):
|
|||
|
||||
async def test_unload_config_entry(hass):
|
||||
"""Test that unloading works properly."""
|
||||
patch_product_identify(None)
|
||||
setup_product_mock("switches", [])
|
||||
|
||||
entry = mock_config()
|
||||
entry.add_to_hass(hass)
|
||||
|
|
Loading…
Add table
Reference in a new issue