Add enum util (#87082)

* Add enum helper

* docstring

* Move to util

* Add use case
This commit is contained in:
epenet 2023-02-01 15:00:27 +01:00 committed by GitHub
parent 8efd01b2e8
commit 1225c5e97d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 6 deletions

View File

@ -3,7 +3,6 @@ from __future__ import annotations
import asyncio
from collections.abc import Mapping
from contextlib import suppress
from dataclasses import dataclass
from datetime import date, datetime, timedelta, timezone
from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
@ -59,6 +58,7 @@ from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.restore_state import ExtraStoredData, RestoreEntity
from homeassistant.helpers.typing import UNDEFINED, ConfigType, StateType, UndefinedType
from homeassistant.util import dt as dt_util
from homeassistant.util.enum import try_parse_enum
from .const import ( # noqa: F401
ATTR_LAST_RESET,
@ -464,11 +464,9 @@ class SensorEntity(Entity):
native_unit_of_measurement = self.native_unit_of_measurement
unit_of_measurement = self.unit_of_measurement
value = self.native_value
device_class: SensorDeviceClass | None = None
with suppress(ValueError):
# For the sake of validation, we can ignore custom device classes
# (customization and legacy style translations)
device_class = SensorDeviceClass(str(self.device_class))
# For the sake of validation, we can ignore custom device classes
# (customization and legacy style translations)
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
state_class = self.state_class
# Sensors with device classes indicating a non-numeric value

View File

@ -0,0 +1,16 @@
"""Helpers for working with enums."""
import contextlib
from enum import Enum
from typing import Any, TypeVar
_EnumT = TypeVar("_EnumT", bound=Enum)
def try_parse_enum(cls: type[_EnumT], value: Any) -> _EnumT | None:
"""Try to parse the value into an Enum.
Return None if parsing fails.
"""
with contextlib.suppress(ValueError):
return cls(value)
return None

51
tests/util/test_enum.py Normal file
View File

@ -0,0 +1,51 @@
"""Test enum helpers."""
from enum import Enum, IntEnum, IntFlag
from typing import Any
import pytest
from homeassistant.backports.enum import StrEnum
from homeassistant.util.enum import try_parse_enum
class _AStrEnum(StrEnum):
VALUE = "value"
class _AnIntEnum(IntEnum):
VALUE = 1
class _AnIntFlag(IntFlag):
VALUE = 1
@pytest.mark.parametrize(
"enum_type,value,expected",
[
# StrEnum valid checks
(_AStrEnum, _AStrEnum.VALUE, _AStrEnum.VALUE),
(_AStrEnum, "value", _AStrEnum.VALUE),
# StrEnum invalid checks
(_AStrEnum, "invalid", None),
(_AStrEnum, 1, None),
(_AStrEnum, None, None),
# IntEnum valid checks
(_AnIntEnum, _AnIntEnum.VALUE, _AnIntEnum.VALUE),
(_AnIntEnum, 1, _AnIntEnum.VALUE),
# IntEnum invalid checks
(_AnIntEnum, "value", None),
(_AnIntEnum, 2, None),
(_AnIntEnum, None, None),
# IntFlag valid checks
(_AnIntFlag, _AnIntFlag.VALUE, _AnIntFlag.VALUE),
(_AnIntFlag, 1, _AnIntFlag.VALUE),
(_AnIntFlag, 2, _AnIntFlag(2)),
# IntFlag invalid checks
(_AnIntFlag, "value", None),
(_AnIntFlag, None, None),
],
)
def test_try_parse(enum_type: type[Enum], value: Any, expected: Enum | None) -> None:
"""Test parsing of values into an Enum."""
assert try_parse_enum(enum_type, value) is expected