mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00: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:
parent
2fc34e7cce
commit
eb469d6a2f
@ -5,12 +5,11 @@ from collections.abc import Callable
|
|||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
from typing import Any, Generic, NamedTuple, TypeVar, cast, overload
|
from typing import Any, Generic, NamedTuple, TypeVar, cast
|
||||||
|
|
||||||
from aioesphomeapi import (
|
from aioesphomeapi import (
|
||||||
APIClient,
|
APIClient,
|
||||||
APIConnectionError,
|
APIConnectionError,
|
||||||
APIIntEnum,
|
|
||||||
APIVersion,
|
APIVersion,
|
||||||
DeviceInfo as EsphomeDeviceInfo,
|
DeviceInfo as EsphomeDeviceInfo,
|
||||||
EntityCategory as EsphomeEntityCategory,
|
EntityCategory as EsphomeEntityCategory,
|
||||||
@ -64,6 +63,7 @@ from .domain_data import DomainData
|
|||||||
|
|
||||||
# Import config flow so that it's added to the registry
|
# Import config flow so that it's added to the registry
|
||||||
from .entry_data import RuntimeEntryData
|
from .entry_data import RuntimeEntryData
|
||||||
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
|
|
||||||
CONF_DEVICE_NAME = "device_name"
|
CONF_DEVICE_NAME = "device_name"
|
||||||
CONF_NOISE_PSK = "noise_psk"
|
CONF_NOISE_PSK = "noise_psk"
|
||||||
@ -687,41 +687,6 @@ def esphome_state_property(
|
|||||||
return _wrapper
|
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)
|
ICON_SCHEMA = vol.Schema(cv.icon)
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,12 +54,8 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import (
|
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||||
EsphomeEntity,
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
EsphomeEnumMapper,
|
|
||||||
esphome_state_property,
|
|
||||||
platform_async_setup_entry,
|
|
||||||
)
|
|
||||||
|
|
||||||
FAN_QUIET = "quiet"
|
FAN_QUIET = "quiet"
|
||||||
|
|
||||||
|
39
homeassistant/components/esphome/enum_mapper.py
Normal file
39
homeassistant/components/esphome/enum_mapper.py
Normal 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]
|
@ -22,12 +22,8 @@ from homeassistant.util.percentage import (
|
|||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import (
|
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||||
EsphomeEntity,
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
EsphomeEnumMapper,
|
|
||||||
esphome_state_property,
|
|
||||||
platform_async_setup_entry,
|
|
||||||
)
|
|
||||||
|
|
||||||
ORDERED_NAMED_FAN_SPEEDS = [FanSpeed.LOW, FanSpeed.MEDIUM, FanSpeed.HIGH]
|
ORDERED_NAMED_FAN_SPEEDS = [FanSpeed.LOW, FanSpeed.MEDIUM, FanSpeed.HIGH]
|
||||||
|
|
||||||
|
@ -24,12 +24,8 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import (
|
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||||
EsphomeEntity,
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
EsphomeEnumMapper,
|
|
||||||
esphome_state_property,
|
|
||||||
platform_async_setup_entry,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
@ -11,12 +11,8 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.enum import try_parse_enum
|
from homeassistant.util.enum import try_parse_enum
|
||||||
|
|
||||||
from . import (
|
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||||
EsphomeEntity,
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
EsphomeEnumMapper,
|
|
||||||
esphome_state_property,
|
|
||||||
platform_async_setup_entry,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
@ -24,12 +24,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.util import dt
|
from homeassistant.util import dt
|
||||||
from homeassistant.util.enum import try_parse_enum
|
from homeassistant.util.enum import try_parse_enum
|
||||||
|
|
||||||
from . import (
|
from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||||
EsphomeEntity,
|
from .enum_mapper import EsphomeEnumMapper
|
||||||
EsphomeEnumMapper,
|
|
||||||
esphome_state_property,
|
|
||||||
platform_async_setup_entry,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
42
tests/components/esphome/test_enum_mapper.py
Normal file
42
tests/components/esphome/test_enum_mapper.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user