1
mirror of https://github.com/home-assistant/core synced 2024-10-04 07:58:43 +02:00

Move enum mapper to own file to prevent circular dependency (#90890)

* Move enum_mapper to own file to prevent circular dependency

* Add enum mapper test
This commit is contained in:
Jesse Hills 2023-04-06 14:55:51 +12:00 committed by GitHub
parent 2fc34e7cce
commit eb469d6a2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 93 additions and 67 deletions

View File

@ -5,12 +5,11 @@ from collections.abc import Callable
import functools
import logging
import math
from typing import Any, Generic, NamedTuple, TypeVar, cast, overload
from typing import Any, Generic, NamedTuple, TypeVar, cast
from aioesphomeapi import (
APIClient,
APIConnectionError,
APIIntEnum,
APIVersion,
DeviceInfo as EsphomeDeviceInfo,
EntityCategory as EsphomeEntityCategory,
@ -64,6 +63,7 @@ from .domain_data import DomainData
# Import config flow so that it's added to the registry
from .entry_data import RuntimeEntryData
from .enum_mapper import EsphomeEnumMapper
CONF_DEVICE_NAME = "device_name"
CONF_NOISE_PSK = "noise_psk"
@ -687,41 +687,6 @@ def esphome_state_property(
return _wrapper
_EnumT = TypeVar("_EnumT", bound=APIIntEnum)
_ValT = TypeVar("_ValT")
class EsphomeEnumMapper(Generic[_EnumT, _ValT]):
"""Helper class to convert between hass and esphome enum values."""
def __init__(self, mapping: dict[_EnumT, _ValT]) -> None:
"""Construct a EsphomeEnumMapper."""
# Add none mapping
augmented_mapping: dict[
_EnumT | None, _ValT | None
] = mapping # type: ignore[assignment]
augmented_mapping[None] = None
self._mapping = augmented_mapping
self._inverse: dict[_ValT, _EnumT] = {v: k for k, v in mapping.items()}
@overload
def from_esphome(self, value: _EnumT) -> _ValT:
...
@overload
def from_esphome(self, value: _EnumT | None) -> _ValT | None:
...
def from_esphome(self, value: _EnumT | None) -> _ValT | None:
"""Convert from an esphome int representation to a hass string."""
return self._mapping[value]
def from_hass(self, value: _ValT) -> _EnumT:
"""Convert from a hass string to a esphome int representation."""
return self._inverse[value]
ICON_SCHEMA = vol.Schema(cv.icon)

View File

@ -54,12 +54,8 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
from .enum_mapper import EsphomeEnumMapper
FAN_QUIET = "quiet"

View File

@ -0,0 +1,39 @@
"""Helper class to convert between Home Assistant and ESPHome enum values."""
from typing import Generic, TypeVar, overload
from aioesphomeapi import APIIntEnum
_EnumT = TypeVar("_EnumT", bound=APIIntEnum)
_ValT = TypeVar("_ValT")
class EsphomeEnumMapper(Generic[_EnumT, _ValT]):
"""Helper class to convert between hass and esphome enum values."""
def __init__(self, mapping: dict[_EnumT, _ValT]) -> None:
"""Construct a EsphomeEnumMapper."""
# Add none mapping
augmented_mapping: dict[
_EnumT | None, _ValT | None
] = mapping # type: ignore[assignment]
augmented_mapping[None] = None
self._mapping = augmented_mapping
self._inverse: dict[_ValT, _EnumT] = {v: k for k, v in mapping.items()}
@overload
def from_esphome(self, value: _EnumT) -> _ValT:
...
@overload
def from_esphome(self, value: _EnumT | None) -> _ValT | None:
...
def from_esphome(self, value: _EnumT | None) -> _ValT | None:
"""Convert from an esphome int representation to a hass string."""
return self._mapping[value]
def from_hass(self, value: _ValT) -> _EnumT:
"""Convert from a hass string to a esphome int representation."""
return self._inverse[value]

View File

@ -22,12 +22,8 @@ from homeassistant.util.percentage import (
ranged_value_to_percentage,
)
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
from .enum_mapper import EsphomeEnumMapper
ORDERED_NAMED_FAN_SPEEDS = [FanSpeed.LOW, FanSpeed.MEDIUM, FanSpeed.HIGH]

View File

@ -24,12 +24,8 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
from .enum_mapper import EsphomeEnumMapper
async def async_setup_entry(

View File

@ -11,12 +11,8 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.enum import try_parse_enum
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
from .enum_mapper import EsphomeEnumMapper
async def async_setup_entry(

View File

@ -24,12 +24,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import dt
from homeassistant.util.enum import try_parse_enum
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
from .enum_mapper import EsphomeEnumMapper
async def async_setup_entry(

View File

@ -0,0 +1,42 @@
"""Test ESPHome enum mapper."""
from aioesphomeapi import APIIntEnum
from homeassistant.backports.enum import StrEnum
from homeassistant.components.esphome.enum_mapper import EsphomeEnumMapper
class MockEnum(APIIntEnum):
"""Mock enum."""
ESPHOME_FOO = 1
ESPHOME_BAR = 2
class MockStrEnum(StrEnum):
"""Mock enum."""
HA_FOO = "foo"
HA_BAR = "bar"
MOCK_MAPPING: EsphomeEnumMapper[MockEnum, MockStrEnum] = EsphomeEnumMapper(
{
MockEnum.ESPHOME_FOO: MockStrEnum.HA_FOO,
MockEnum.ESPHOME_BAR: MockStrEnum.HA_BAR,
}
)
async def test_map_esphome_to_ha() -> None:
"""Test mapping from ESPHome to HA."""
assert MOCK_MAPPING.from_esphome(MockEnum.ESPHOME_FOO) == MockStrEnum.HA_FOO
assert MOCK_MAPPING.from_esphome(MockEnum.ESPHOME_BAR) == MockStrEnum.HA_BAR
async def test_map_ha_to_esphome() -> None:
"""Test mapping from HA to ESPHome."""
assert MOCK_MAPPING.from_hass(MockStrEnum.HA_FOO) == MockEnum.ESPHOME_FOO
assert MOCK_MAPPING.from_hass(MockStrEnum.HA_BAR) == MockEnum.ESPHOME_BAR