From 1d2c2d2055980b138982fd38d7dae84c6f3356fa Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 27 Mar 2024 08:41:44 +0100 Subject: [PATCH] Move SignalTypes to util (#114236) --- homeassistant/components/mqtt/discovery.py | 2 +- homeassistant/const.py | 5 ++- homeassistant/helpers/discovery.py | 7 +--- homeassistant/helpers/dispatcher.py | 41 ++------------------- homeassistant/util/signal_type.py | 43 ++++++++++++++++++++++ tests/helpers/test_dispatcher.py | 3 +- 6 files changed, 55 insertions(+), 46 deletions(-) create mode 100644 homeassistant/util/signal_type.py diff --git a/homeassistant/components/mqtt/discovery.py b/homeassistant/components/mqtt/discovery.py index f50a4e4a3f7..13c56a9b48e 100644 --- a/homeassistant/components/mqtt/discovery.py +++ b/homeassistant/components/mqtt/discovery.py @@ -18,7 +18,6 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResultType import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import ( - SignalTypeFormat, async_dispatcher_connect, async_dispatcher_send, ) @@ -26,6 +25,7 @@ from homeassistant.helpers.service_info.mqtt import MqttServiceInfo from homeassistant.helpers.typing import DiscoveryInfoType from homeassistant.loader import async_get_mqtt from homeassistant.util.json import json_loads_object +from homeassistant.util.signal_type import SignalTypeFormat from .. import mqtt from .abbreviations import ABBREVIATIONS, DEVICE_ABBREVIATIONS, ORIGIN_ABBREVIATIONS diff --git a/homeassistant/const.py b/homeassistant/const.py index 6e657469b9a..ee15cfd72c3 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -13,6 +13,7 @@ from .helpers.deprecation import ( check_if_deprecated_constant, dir_with_deprecated_constants, ) +from .util.signal_type import SignalType APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2024 @@ -1609,7 +1610,9 @@ CAST_APP_ID_HOMEASSISTANT_LOVELACE: Final = "A078F6B0" # User used by Supervisor HASSIO_USER_NAME = "Supervisor" -SIGNAL_BOOTSTRAP_INTEGRATIONS = "bootstrap_integrations" +SIGNAL_BOOTSTRAP_INTEGRATIONS: SignalType[dict[str, float]] = SignalType( + "bootstrap_integrations" +) # hass.data key for logging information. diff --git a/homeassistant/helpers/discovery.py b/homeassistant/helpers/discovery.py index 0bad52dff08..4b5a0117be7 100644 --- a/homeassistant/helpers/discovery.py +++ b/homeassistant/helpers/discovery.py @@ -15,11 +15,8 @@ from homeassistant import core, setup from homeassistant.const import Platform from homeassistant.loader import bind_hass -from .dispatcher import ( - SignalTypeFormat, - async_dispatcher_connect, - async_dispatcher_send, -) +from ..util.signal_type import SignalTypeFormat +from .dispatcher import async_dispatcher_connect, async_dispatcher_send from .typing import ConfigType, DiscoveryInfoType SIGNAL_PLATFORM_DISCOVERED: SignalTypeFormat[DiscoveryDict] = SignalTypeFormat( diff --git a/homeassistant/helpers/dispatcher.py b/homeassistant/helpers/dispatcher.py index 4633e81c78b..c1194c7da01 100644 --- a/homeassistant/helpers/dispatcher.py +++ b/homeassistant/helpers/dispatcher.py @@ -3,57 +3,24 @@ from __future__ import annotations from collections.abc import Callable, Coroutine -from dataclasses import dataclass from functools import partial import logging -from typing import Any, Generic, TypeVarTuple, overload +from typing import Any, TypeVarTuple, overload from homeassistant.core import HassJob, HomeAssistant, callback from homeassistant.loader import bind_hass from homeassistant.util.async_ import run_callback_threadsafe from homeassistant.util.logging import catch_log_exception +# Explicit reexport of 'SignalType' for backwards compatibility +from homeassistant.util.signal_type import SignalType as SignalType # noqa: PLC0414 + _Ts = TypeVarTuple("_Ts") _LOGGER = logging.getLogger(__name__) DATA_DISPATCHER = "dispatcher" -@dataclass(frozen=True) -class _SignalTypeBase(Generic[*_Ts]): - """Generic base class for SignalType.""" - - name: str - - def __hash__(self) -> int: - """Return hash of name.""" - - return hash(self.name) - - def __eq__(self, other: Any) -> bool: - """Check equality for dict keys to be compatible with str.""" - - if isinstance(other, str): - return self.name == other - if isinstance(other, SignalType): - return self.name == other.name - return False - - -@dataclass(frozen=True, eq=False) -class SignalType(_SignalTypeBase[*_Ts]): - """Generic string class for signal to improve typing.""" - - -@dataclass(frozen=True, eq=False) -class SignalTypeFormat(_SignalTypeBase[*_Ts]): - """Generic string class for signal. Requires call to 'format' before use.""" - - def format(self, *args: Any, **kwargs: Any) -> SignalType[*_Ts]: - """Format name and return new SignalType instance.""" - return SignalType(self.name.format(*args, **kwargs)) - - _DispatcherDataType = dict[ SignalType[*_Ts] | str, dict[ diff --git a/homeassistant/util/signal_type.py b/homeassistant/util/signal_type.py new file mode 100644 index 00000000000..be634ce6ba9 --- /dev/null +++ b/homeassistant/util/signal_type.py @@ -0,0 +1,43 @@ +"""Define SignalTypes for dispatcher.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Generic, TypeVarTuple + +_Ts = TypeVarTuple("_Ts") + + +@dataclass(frozen=True) +class _SignalTypeBase(Generic[*_Ts]): + """Generic base class for SignalType.""" + + name: str + + def __hash__(self) -> int: + """Return hash of name.""" + + return hash(self.name) + + def __eq__(self, other: Any) -> bool: + """Check equality for dict keys to be compatible with str.""" + + if isinstance(other, str): + return self.name == other + if isinstance(other, SignalType): + return self.name == other.name + return False + + +@dataclass(frozen=True, eq=False) +class SignalType(_SignalTypeBase[*_Ts]): + """Generic string class for signal to improve typing.""" + + +@dataclass(frozen=True, eq=False) +class SignalTypeFormat(_SignalTypeBase[*_Ts]): + """Generic string class for signal. Requires call to 'format' before use.""" + + def format(self, *args: Any, **kwargs: Any) -> SignalType[*_Ts]: + """Format name and return new SignalType instance.""" + return SignalType(self.name.format(*args, **kwargs)) diff --git a/tests/helpers/test_dispatcher.py b/tests/helpers/test_dispatcher.py index 1e1abe6e154..149231a9368 100644 --- a/tests/helpers/test_dispatcher.py +++ b/tests/helpers/test_dispatcher.py @@ -6,11 +6,10 @@ import pytest from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import ( - SignalType, - SignalTypeFormat, async_dispatcher_connect, async_dispatcher_send, ) +from homeassistant.util.signal_type import SignalType, SignalTypeFormat async def test_simple_function(hass: HomeAssistant) -> None: