Skip to content

Commit

Permalink
Freeze dataclasses which inherit from EntityDescription
Browse files Browse the repository at this point in the history
... but only on versions of HA which support this.
  • Loading branch information
canton7 committed Dec 24, 2023
1 parent 48b90a2 commit ff5b2c0
Show file tree
Hide file tree
Showing 12 changed files with 33 additions and 21 deletions.
18 changes: 10 additions & 8 deletions custom_components/foxess_modbus/entities/entity_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,27 @@
from ..common.register_type import RegisterType
from .inverter_model_spec import InverterModelSpec

# HA introduced a FrozenOrThawed metaclass which is used by EntityDescription.
# This conflicts with ABC's metaclass.
# If EntityDescription has a metaclass (FrozenOrThawed), we need to combine that with
# ABC's metaclass.
# ABC's metaclass, see https://github.com/nathanmarlor/foxess_modbus/issues/480.
# This is to allow HA to move to frozen entity descriptions (to aid caching), and will
# start logging deprecation warnings in 2024.x.
if type(EntityDescription) == type(type): # type: ignore
METACLASS = type(ABC)
_METACLASS = type(ABC)
ENTITY_DESCRIPTION_KWARGS = {}
else:

class EntityFactoryMetaclass(type(EntityDescription), type(ABC)): # type: ignore
"""
Metaclass to use for EntityFactory.
HA introduced a FrozenOrThawed metaclass which is used by EntityDescription.
This conflicts with ABC's metaclass.
See https://github.com/nathanmarlor/foxess_modbus/issues/480
"""

METACLASS = EntityFactoryMetaclass
_METACLASS = EntityFactoryMetaclass
ENTITY_DESCRIPTION_KWARGS = {"frozen": True}


class EntityFactory(ABC, metaclass=METACLASS): # type: ignore
class EntityFactory(ABC, metaclass=_METACLASS): # type: ignore
"""Factory which can create entities"""

@property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@

from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .inverter_model_spec import ModbusAddressSpec
from .modbus_sensor import ModbusSensor
from .modbus_sensor import ModbusSensorDescription


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusBatterySensorDescription(ModbusSensorDescription):
"""Description for ModbusBatterySensor"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .base_validator import BaseValidator
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import InverterModelSpec
from .modbus_entity_mixin import ModbusEntityMixin

_LOGGER = logging.getLogger(__name__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusBinarySensorDescription(BinarySensorEntityDescription, EntityFactory):
"""Description for ModbusBinarySensor"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# mypy: disable-error-code="call-arg"


@dataclass
@dataclass(frozen=True)
class ModbusChargePeriodAddressConfig:
"""Defines the set of registers which are used to define a charge period"""

Expand All @@ -31,7 +31,7 @@ class ModbusChargePeriodAddressConfig:
enable_charge_from_grid_address: int


@dataclass
@dataclass(frozen=True)
class ModbusChargePeriodInfo:
addresses: ModbusChargePeriodAddressConfig
period_start_entity_id: str
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .base_validator import BaseValidator
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import InverterModelSpec
from .modbus_entity_mixin import ModbusEntityMixin
Expand Down Expand Up @@ -53,7 +54,7 @@ def _is_force_charge_enabled(
return start_or_end_1 > 0 or start_or_end_2 > 0


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusChargePeriodStartEndSensorDescription(SensorEntityDescription, EntityFactory):
"""Entity description for ModbusChargePeriodStartEndSensor"""

Expand Down Expand Up @@ -179,7 +180,7 @@ def addresses(self) -> list[int]:
return [self._address, self._other_address]


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusEnableForceChargeSensorDescription(BinarySensorEntityDescription, EntityFactory):
"""Entity description for ModbusEnableForceChargeSensor"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import ModbusAddressesSpec
from .modbus_entity_mixin import ModbusEntityMixin
Expand Down Expand Up @@ -155,7 +156,7 @@
assert any(fault for fault_list in _FAULTS for fault in fault_list if fault == assert_mask)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusFaultSensorDescription(SensorEntityDescription, EntityFactory):
"""Description for ModbusFaultSensor"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import EntitySpec
from .modbus_entity_mixin import ModbusEntityMixin
Expand All @@ -23,7 +24,7 @@
_LOGGER = logging.getLogger(__name__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusIntegrationSensorDescription(SensorEntityDescription, EntityFactory):
"""Custom sensor description"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import ModbusAddressSpec
from .modbus_entity_mixin import ModbusEntityMixin
Expand All @@ -37,7 +38,7 @@
]


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusInverterStateSensorDescription(SensorEntityDescription, EntityFactory):
"""Description for ModbusInverterStateSensor"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import EntitySpec
from .modbus_entity_mixin import ModbusEntityMixin
Expand All @@ -23,7 +24,7 @@
_LOGGER = logging.getLogger(__name__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusLambdaSensorDescription(SensorEntityDescription, EntityFactory):
"""Entity description for ModbusLambdaSensors"""

Expand Down
3 changes: 2 additions & 1 deletion custom_components/foxess_modbus/entities/modbus_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .base_validator import BaseValidator
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import ModbusAddressSpec
from .modbus_entity_mixin import ModbusEntityMixin

_LOGGER: logging.Logger = logging.getLogger(__package__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusNumberDescription(NumberEntityDescription, EntityFactory):
"""Custom number entity description"""

Expand Down
3 changes: 2 additions & 1 deletion custom_components/foxess_modbus/entities/modbus_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
from ..common.entity_controller import EntityController
from ..common.register_type import RegisterType
from .base_validator import BaseValidator
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import ModbusAddressSpec
from .modbus_entity_mixin import ModbusEntityMixin

_LOGGER: logging.Logger = logging.getLogger(__package__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusSelectDescription(SelectEntityDescription, EntityFactory):
"""Custom select entity description"""

Expand Down
3 changes: 2 additions & 1 deletion custom_components/foxess_modbus/entities/modbus_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
from ..common.register_type import RegisterType
from ..const import ROUND_SENSOR_VALUES
from .base_validator import BaseValidator
from .entity_factory import ENTITY_DESCRIPTION_KWARGS
from .entity_factory import EntityFactory
from .inverter_model_spec import ModbusAddressesSpec
from .modbus_entity_mixin import ModbusEntityMixin

_LOGGER = logging.getLogger(__name__)


@dataclass(kw_only=True)
@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusSensorDescription(SensorEntityDescription, EntityFactory):
"""Custom sensor description"""

Expand Down

0 comments on commit ff5b2c0

Please sign in to comment.