Change device entry type to an StrEnum (#59940)

Co-authored-by: Ville Skyttä <ville.skytta@iki.fi>
Co-authored-by: Franck Nijhof <git@frenck.dev>
pull/60164/head
Ville Skyttä 2021-11-22 19:14:15 +02:00 committed by GitHub
parent 4a5238efa5
commit 053c456199
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 167 additions and 71 deletions

View File

@ -7,6 +7,7 @@ from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_NAME, DEVICE_CLASS_TEMPERATURE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -95,7 +96,7 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
self._unit_system = API_IMPERIAL
self._attr_native_unit_of_measurement = description.unit_imperial
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.location_key)},
manufacturer=MANUFACTURER,
name=NAME,

View File

@ -19,6 +19,7 @@ from homeassistant.components.weather import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -68,7 +69,7 @@ class AccuWeatherEntity(CoordinatorEntity, WeatherEntity):
)
self._attr_attribution = ATTRIBUTION
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.location_key)},
manufacturer=MANUFACTURER,
name=NAME,

View File

@ -21,6 +21,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import (
@ -197,7 +198,7 @@ class AdGuardHomeDeviceEntity(AdGuardHomeEntity):
def device_info(self) -> DeviceInfo:
"""Return device information about this AdGuard Home instance."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={
(DOMAIN, self.adguard.host, self.adguard.port, self.adguard.base_path) # type: ignore
},

View File

@ -27,6 +27,7 @@ from homeassistant.const import (
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -154,7 +155,7 @@ class AirlySensor(CoordinatorEntity, SensorEntity):
"""Initialize."""
super().__init__(coordinator)
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, f"{coordinator.latitude}-{coordinator.longitude}")},
manufacturer=MANUFACTURER,
name=DEFAULT_NAME,

View File

@ -21,8 +21,6 @@ DOMAIN: Final = "ambee"
LOGGER = logging.getLogger(__package__)
SCAN_INTERVAL = timedelta(hours=1)
ENTRY_TYPE_SERVICE: Final = "service"
DEVICE_CLASS_AMBEE_RISK: Final = "ambee__risk"
SERVICE_AIR_QUALITY: Final = "air_quality"

View File

@ -8,6 +8,7 @@ from homeassistant.components.sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -16,7 +17,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
)
from .const import DOMAIN, ENTRY_TYPE_SERVICE, SENSORS, SERVICES
from .const import DOMAIN, SENSORS, SERVICES
async def async_setup_entry(
@ -59,7 +60,7 @@ class AmbeeSensorEntity(CoordinatorEntity, SensorEntity):
self._attr_unique_id = f"{entry_id}_{service_key}_{description.key}"
self._attr_device_info = DeviceInfo(
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, f"{entry_id}_{service_key}")},
manufacturer="Ambee",
name=service,

View File

@ -10,6 +10,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
@ -140,7 +141,7 @@ class AuroraEntity(CoordinatorEntity):
def device_info(self) -> DeviceInfo:
"""Define the device based on name."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, str(self.unique_id))},
manufacturer="NOAA",
model="Aurora Visibility Sensor",

View File

@ -14,6 +14,7 @@ import aiohttp
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
@ -120,7 +121,7 @@ class AzureDevOpsDeviceEntity(AzureDevOpsEntity):
def device_info(self) -> DeviceInfo:
"""Return device information about this Azure DevOps instance."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self._organization, self._project_name)}, # type: ignore
manufacturer=self._organization,
name=self._project_name,

View File

@ -21,6 +21,7 @@ from homeassistant.const import (
PERCENTAGE,
)
from homeassistant.helpers import config_validation as cv, update_coordinator
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import StateType
@ -104,7 +105,7 @@ class CO2Sensor(update_coordinator.CoordinatorEntity[CO2SignalResponse], SensorE
}
self._attr_device_info = DeviceInfo(
configuration_url="https://www.electricitymap.org/",
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.entry_id)},
manufacturer="Tmrow.com",
name="CO2 signal",

View File

@ -2,7 +2,6 @@
from __future__ import annotations
from datetime import timedelta
from typing import Final
from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
from homeassistant.const import (
@ -21,7 +20,6 @@ CONF_DECLINATION = "declination"
CONF_AZIMUTH = "azimuth"
CONF_MODULES_POWER = "modules power"
CONF_DAMPING = "damping"
ENTRY_TYPE_SERVICE: Final = "service"
SENSORS: tuple[ForecastSolarSensorEntityDescription, ...] = (
ForecastSolarSensorEntityDescription(

View File

@ -6,6 +6,7 @@ from datetime import datetime
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -14,7 +15,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
)
from .const import DOMAIN, ENTRY_TYPE_SERVICE, SENSORS
from .const import DOMAIN, SENSORS
from .models import ForecastSolarSensorEntityDescription
@ -53,7 +54,7 @@ class ForecastSolarSensorEntity(CoordinatorEntity, SensorEntity):
self._attr_unique_id = f"{entry_id}_{entity_description.key}"
self._attr_device_info = DeviceInfo(
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, entry_id)},
manufacturer="Forecast.Solar",
model=coordinator.data.account_type.value,

View File

@ -8,6 +8,7 @@ from homeassistant.components.sensor import DOMAIN as PLATFORM, SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_NAME, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity_registry import async_get_registry
@ -83,7 +84,7 @@ class GiosSensor(CoordinatorEntity, SensorEntity):
"""Initialize."""
super().__init__(coordinator)
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, str(coordinator.gios.station_id))},
manufacturer=MANUFACTURER,
name=DEFAULT_NAME,

View File

@ -22,6 +22,7 @@ from homeassistant.const import (
)
from homeassistant.core import CoreState, HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util
@ -213,7 +214,7 @@ class GoogleTravelTimeSensor(SensorEntity):
def device_info(self) -> DeviceInfo:
"""Return device specific attributes."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self._api_key)},
name=DOMAIN,
)

View File

@ -121,7 +121,7 @@ class KrakenSensor(CoordinatorEntity[Optional[KrakenResponse]], SensorEntity):
self._available = True
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=device_registry.DeviceEntryType.SERVICE,
identifiers={(DOMAIN, f"{source_asset}_{self._target_asset}")},
manufacturer="Kraken.com",
name=self._device_name,

View File

@ -36,6 +36,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@ -281,7 +282,7 @@ class MetWeather(CoordinatorEntity, WeatherEntity):
"""Device info."""
return DeviceInfo(
default_name="Forecast",
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN,)}, # type: ignore[arg-type]
manufacturer="Met.no",
model="Forecast",

View File

@ -1,6 +1,7 @@
"""mütesync binary sensor entities."""
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.helpers import update_coordinator
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from .const import DOMAIN
@ -46,7 +47,7 @@ class MuteStatus(update_coordinator.CoordinatorEntity, BinarySensorEntity):
def device_info(self) -> DeviceInfo:
"""Return the device info of the sensor."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self.coordinator.data["user-id"])},
manufacturer="mütesync",
model="mutesync app",

View File

@ -5,6 +5,7 @@ from homeassistant.components.sensor import SensorEntity, SensorEntityDescriptio
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -80,7 +81,7 @@ class AbstractOpenWeatherMapSensor(SensorEntity):
self._attr_unique_id = unique_id
split_unique_id = unique_id.split("-")
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, f"{split_unique_id[0]}-{split_unique_id[1]}")},
manufacturer=MANUFACTURER,
name=DEFAULT_NAME,

View File

@ -5,6 +5,7 @@ from homeassistant.components.weather import Forecast, WeatherEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PRESSURE_HPA, PRESSURE_INHG, TEMP_CELSIUS
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.pressure import convert as pressure_convert
@ -71,7 +72,7 @@ class OpenWeatherMapWeather(WeatherEntity):
def device_info(self) -> DeviceInfo:
"""Return the device info."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self._unique_id)},
manufacturer=MANUFACTURER,
name=DEFAULT_NAME,

View File

@ -9,8 +9,6 @@ DOMAIN: Final = "p1_monitor"
LOGGER = logging.getLogger(__package__)
SCAN_INTERVAL = timedelta(seconds=5)
ENTRY_TYPE_SERVICE: Final = "service"
SERVICE_SMARTMETER: Final = "smartmeter"
SERVICE_PHASES: Final = "phases"
SERVICE_SETTINGS: Final = "settings"

View File

@ -25,6 +25,7 @@ from homeassistant.const import (
VOLUME_CUBIC_METERS,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -33,7 +34,6 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import P1MonitorDataUpdateCoordinator
from .const import (
DOMAIN,
ENTRY_TYPE_SERVICE,
SERVICE_PHASES,
SERVICE_SETTINGS,
SERVICE_SMARTMETER,
@ -264,7 +264,7 @@ class P1MonitorSensorEntity(CoordinatorEntity, SensorEntity):
)
self._attr_device_info = DeviceInfo(
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={
(DOMAIN, f"{coordinator.config_entry.entry_id}_{service_key}")
},

View File

@ -6,6 +6,7 @@ from typing import Any, cast
from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import (
@ -79,7 +80,7 @@ class PicnicSensor(SensorEntity, CoordinatorEntity):
def device_info(self) -> DeviceInfo:
"""Return device info."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, cast(str, self._service_unique_id))},
manufacturer="Picnic",
model=self._service_unique_id,

View File

@ -13,6 +13,7 @@ from homeassistant.components.binary_sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
@ -20,7 +21,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
)
from .const import DOMAIN, ENTRY_TYPE_SERVICE
from .const import DOMAIN
@dataclass
@ -87,7 +88,7 @@ class RDWBinarySensorEntity(CoordinatorEntity, BinarySensorEntity):
self._attr_unique_id = f"{coordinator.data.license_plate}_{description.key}"
self._attr_device_info = DeviceInfo(
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.data.license_plate)},
manufacturer=coordinator.data.brand,
name=f"{coordinator.data.brand}: {coordinator.data.license_plate}",

View File

@ -10,5 +10,4 @@ DOMAIN: Final = "rdw"
LOGGER = logging.getLogger(__package__)
SCAN_INTERVAL = timedelta(hours=1)
ENTRY_TYPE_SERVICE: Final = "service"
CONF_LICENSE_PLATE: Final = "license_plate"

View File

@ -14,6 +14,7 @@ from homeassistant.components.sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
@ -21,7 +22,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
)
from .const import CONF_LICENSE_PLATE, DOMAIN, ENTRY_TYPE_SERVICE
from .const import CONF_LICENSE_PLATE, DOMAIN
@dataclass
@ -89,7 +90,7 @@ class RDWSensorEntity(CoordinatorEntity, SensorEntity):
self._attr_unique_id = f"{license_plate}_{description.key}"
self._attr_device_info = DeviceInfo(
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, f"{license_plate}")},
manufacturer=coordinator.data.brand,
name=f"{coordinator.data.brand}: {coordinator.data.license_plate}",

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from sonarr import Sonarr
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import DOMAIN
@ -38,6 +39,6 @@ class SonarrEntity(Entity):
name="Activity Sensor",
manufacturer="Sonarr",
sw_version=self.sonarr.app.info.version,
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
configuration_url=configuration_url,
)

View File

@ -8,6 +8,7 @@ from homeassistant.components.speedtestdotnet import SpeedTestDataCoordinator
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.restore_state import RestoreEntity
@ -64,7 +65,7 @@ class SpeedtestSensor(CoordinatorEntity, RestoreEntity, SensorEntity):
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self.coordinator.config_entry.entry_id)},
name=DEFAULT_NAME,
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
configuration_url="https://www.speedtest.net/",
)

View File

@ -15,11 +15,12 @@ from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import CONF_PROVINCE, DOMAIN, ENTRY_TYPE_SERVICE, LOGGER, PROVINCES
from .const import CONF_PROVINCE, DOMAIN, LOGGER, PROVINCES
DEFAULT_NAME = "Stookalert"
ATTRIBUTION = "Data provided by rivm.nl"
@ -83,7 +84,7 @@ class StookalertBinarySensor(BinarySensorEntity):
name=entry.data[CONF_PROVINCE],
manufacturer="RIVM",
model="Stookalert",
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
configuration_url="https://www.rivm.nl/stookalert",
)

View File

@ -21,5 +21,3 @@ PROVINCES: Final = (
"Zeeland",
"Zuid-Holland",
)
ENTRY_TYPE_SERVICE: Final = "service"

View File

@ -5,6 +5,7 @@ import aiosyncthing
from homeassistant.components.sensor import SensorEntity
from homeassistant.core import callback
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.event import async_track_time_interval
@ -134,7 +135,7 @@ class FolderSensor(SensorEntity):
def device_info(self) -> DeviceInfo:
"""Return device information."""
return DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self._server_id)},
manufacturer="Syncthing Team",
name=f"Syncthing ({self._syncthing.url})",

View File

@ -11,5 +11,3 @@ SCAN_INTERVAL = timedelta(hours=1)
CONF_POST_CODE = "post_code"
CONF_HOUSE_NUMBER = "house_number"
CONF_HOUSE_LETTER = "house_letter"
ENTRY_TYPE_SERVICE: Final = "service"

View File

@ -10,6 +10,7 @@ from homeassistant.components.sensor import SensorEntity, SensorEntityDescriptio
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID, DEVICE_CLASS_DATE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
@ -17,7 +18,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator,
)
from .const import DOMAIN, ENTRY_TYPE_SERVICE
from .const import DOMAIN
@dataclass
@ -96,7 +97,7 @@ class TwenteMilieuSensor(CoordinatorEntity, SensorEntity):
self._attr_unique_id = f"{DOMAIN}_{entry.data[CONF_ID]}_{description.key}"
self._attr_device_info = DeviceInfo(
configuration_url="https://www.twentemilieu.nl",
entry_type=ENTRY_TYPE_SERVICE,
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, str(entry.data[CONF_ID]))},
manufacturer="Twente Milieu",
name="Twente Milieu",

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from pyuptimerobot import UptimeRobotMonitor
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
@ -31,7 +32,7 @@ class UptimeRobotEntity(CoordinatorEntity):
identifiers={(DOMAIN, str(self.monitor.id))},
name=self.monitor.friendly_name,
manufacturer="UptimeRobot Team",
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
model=self.monitor.type.name,
configuration_url=f"https://uptimerobot.com/dashboard#{self.monitor.id}",
)

View File

@ -36,6 +36,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@ -142,7 +143,7 @@ class VlcDevice(MediaPlayerEntity):
config_entry_id = config_entry.entry_id
self._attr_unique_id = config_entry_id
self._attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, config_entry_id)},
manufacturer="VideoLAN",
name=name,

View File

@ -22,6 +22,7 @@ from homeassistant.const import (
)
from homeassistant.core import Config, CoreState, HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import DiscoveryInfoType
@ -165,7 +166,7 @@ class WazeTravelTime(SensorEntity):
_attr_native_unit_of_measurement = TIME_MINUTES
_attr_device_info = DeviceInfo(
entry_type="service",
entry_type=DeviceEntryType.SERVICE,
name="Waze",
identifiers={(DOMAIN, DOMAIN)},
)

View File

@ -11,7 +11,9 @@ import attr
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import RequiredParameterMissing
from homeassistant.helpers.frame import report
from homeassistant.loader import bind_hass
from homeassistant.util.enum import StrEnum
import homeassistant.util.uuid as uuid_util
from .debounce import Debouncer
@ -49,6 +51,12 @@ class _DeviceIndex(NamedTuple):
connections: dict[tuple[str, str], str]
class DeviceEntryType(StrEnum):
"""Device entry type."""
SERVICE = "service"
@attr.s(slots=True, frozen=True)
class DeviceEntry:
"""Device Registry Entry."""
@ -68,7 +76,7 @@ class DeviceEntry:
)
),
)
entry_type: str | None = attr.ib(default=None)
entry_type: DeviceEntryType | None = attr.ib(default=None)
id: str = attr.ib(factory=uuid_util.random_uuid_hex)
identifiers: set[tuple[str, str]] = attr.ib(converter=set, factory=set)
manufacturer: str | None = attr.ib(default=None)
@ -254,7 +262,7 @@ class DeviceRegistry:
default_name: str | None | UndefinedType = UNDEFINED,
# To disable a device if it gets created
disabled_by: str | None | UndefinedType = UNDEFINED,
entry_type: str | None | UndefinedType = UNDEFINED,
entry_type: DeviceEntryType | None | UndefinedType = UNDEFINED,
identifiers: set[tuple[str, str]] | None = None,
manufacturer: str | None | UndefinedType = UNDEFINED,
model: str | None | UndefinedType = UNDEFINED,
@ -303,6 +311,14 @@ class DeviceRegistry:
else:
via_device_id = UNDEFINED
if isinstance(entry_type, str) and not isinstance(entry_type, DeviceEntryType):
report( # type: ignore[unreachable]
"uses str for device registry entry_type. This is deprecated, "
"it should be updated to use DeviceEntryType instead",
error_if_core=False,
)
entry_type = DeviceEntryType(entry_type)
device = self._async_update_device(
device.id,
add_config_entry_id=config_entry_id,
@ -370,7 +386,7 @@ class DeviceRegistry:
area_id: str | None | UndefinedType = UNDEFINED,
configuration_url: str | None | UndefinedType = UNDEFINED,
disabled_by: str | None | UndefinedType = UNDEFINED,
entry_type: str | None | UndefinedType = UNDEFINED,
entry_type: DeviceEntryType | None | UndefinedType = UNDEFINED,
manufacturer: str | None | UndefinedType = UNDEFINED,
merge_connections: set[tuple[str, str]] | UndefinedType = UNDEFINED,
merge_identifiers: set[tuple[str, str]] | UndefinedType = UNDEFINED,
@ -511,7 +527,9 @@ class DeviceRegistry:
name=device["name"],
sw_version=device["sw_version"],
# Introduced in 0.110
entry_type=device.get("entry_type"),
entry_type=DeviceEntryType(device["entry_type"])
if device.get("entry_type")
else None,
id=device["id"],
# Introduced in 0.79
# renamed in 0.95

View File

@ -37,6 +37,7 @@ from homeassistant.const import (
from homeassistant.core import CALLBACK_TYPE, Context, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError, NoEntitySpecifiedError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.event import Event, async_track_entity_registry_updated_event
from homeassistant.helpers.typing import StateType
@ -168,7 +169,7 @@ class DeviceInfo(TypedDict, total=False):
default_manufacturer: str
default_model: str
default_name: str
entry_type: str | None
entry_type: DeviceEntryType | None
identifiers: set[tuple[str, str]]
manufacturer: str | None
model: str | None

View File

@ -0,0 +1,31 @@
"""Enum related utilities."""
from __future__ import annotations
from enum import Enum
from typing import Any
class StrEnum(str, Enum):
"""Partial backport of Python 3.11's StrEnum for our basic use cases."""
def __new__(cls, value: str, *args: Any, **kwargs: Any) -> StrEnum:
"""Create a new StrEnum instance."""
if not isinstance(value, str):
raise TypeError(f"{value!r} is not a string")
return super().__new__(cls, value, *args, **kwargs) # type: ignore[call-overload,no-any-return]
def __str__(self) -> str:
"""Return self.value."""
return str(self.value)
@staticmethod
def _generate_next_value_( # pylint: disable=arguments-differ # https://github.com/PyCQA/pylint/issues/5371
name: str, start: int, count: int, last_values: list[Any]
) -> Any:
"""
Make `auto()` explicitly unsupported.
We may revisit this when it's very clear that Python 3.11's
`StrEnum.auto()` behavior will no longer change.
"""
raise TypeError("auto() is not supported by this implementation")

View File

@ -3,11 +3,7 @@ from unittest.mock import AsyncMock
import pytest
from homeassistant.components.ambee.const import (
DEVICE_CLASS_AMBEE_RISK,
DOMAIN,
ENTRY_TYPE_SERVICE,
)
from homeassistant.components.ambee.const import DEVICE_CLASS_AMBEE_RISK, DOMAIN
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
@ -147,7 +143,7 @@ async def test_air_quality(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_air_quality")}
assert device_entry.manufacturer == "Ambee"
assert device_entry.name == "Air Quality"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert not device_entry.model
assert not device_entry.sw_version
@ -248,7 +244,7 @@ async def test_pollen(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_pollen")}
assert device_entry.manufacturer == "Ambee"
assert device_entry.name == "Pollen"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert not device_entry.model
assert not device_entry.sw_version

View File

@ -3,7 +3,7 @@ from unittest.mock import MagicMock
import pytest
from homeassistant.components.forecast_solar.const import DOMAIN, ENTRY_TYPE_SERVICE
from homeassistant.components.forecast_solar.const import DOMAIN
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
@ -141,7 +141,7 @@ async def test_sensors(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}")}
assert device_entry.manufacturer == "Forecast.Solar"
assert device_entry.name == "Solar Production Forecast"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert device_entry.model == "public"
assert not device_entry.sw_version

View File

@ -1,7 +1,7 @@
"""Tests for the sensors provided by the P1 Monitor integration."""
import pytest
from homeassistant.components.p1_monitor.const import DOMAIN, ENTRY_TYPE_SERVICE
from homeassistant.components.p1_monitor.const import DOMAIN
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
STATE_CLASS_MEASUREMENT,
@ -80,7 +80,7 @@ async def test_smartmeter(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_smartmeter")}
assert device_entry.manufacturer == "P1 Monitor"
assert device_entry.name == "SmartMeter"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert not device_entry.model
assert not device_entry.sw_version
@ -136,7 +136,7 @@ async def test_phases(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_phases")}
assert device_entry.manufacturer == "P1 Monitor"
assert device_entry.name == "Phases"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert not device_entry.model
assert not device_entry.sw_version
@ -182,7 +182,7 @@ async def test_settings(
assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_settings")}
assert device_entry.manufacturer == "P1 Monitor"
assert device_entry.name == "Settings"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert not device_entry.model
assert not device_entry.sw_version

View File

@ -1,6 +1,6 @@
"""Tests for the sensors provided by the RDW integration."""
from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
from homeassistant.components.rdw.const import DOMAIN, ENTRY_TYPE_SERVICE
from homeassistant.components.rdw.const import DOMAIN
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_FRIENDLY_NAME, ATTR_ICON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
@ -42,7 +42,7 @@ async def test_vehicle_binary_sensors(
assert device_entry.identifiers == {(DOMAIN, "11ZKZ3")}
assert device_entry.manufacturer == "Skoda"
assert device_entry.name == "Skoda: 11ZKZ3"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert device_entry.model == "Citigo"
assert (
device_entry.configuration_url

View File

@ -1,5 +1,5 @@
"""Tests for the sensors provided by the RDW integration."""
from homeassistant.components.rdw.const import DOMAIN, ENTRY_TYPE_SERVICE
from homeassistant.components.rdw.const import DOMAIN
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.const import (
ATTR_DEVICE_CLASS,
@ -52,7 +52,7 @@ async def test_vehicle_sensors(
assert device_entry.identifiers == {(DOMAIN, "11ZKZ3")}
assert device_entry.manufacturer == "Skoda"
assert device_entry.name == "Skoda: 11ZKZ3"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert device_entry.model == "Citigo"
assert (
device_entry.configuration_url

View File

@ -1,5 +1,5 @@
"""Tests for the Twente Milieu sensors."""
from homeassistant.components.twentemilieu.const import DOMAIN, ENTRY_TYPE_SERVICE
from homeassistant.components.twentemilieu.const import DOMAIN
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_FRIENDLY_NAME,
@ -72,7 +72,7 @@ async def test_waste_pickup_sensors(
assert device_entry.identifiers == {(DOMAIN, "12345")}
assert device_entry.manufacturer == "Twente Milieu"
assert device_entry.name == "Twente Milieu"
assert device_entry.entry_type == ENTRY_TYPE_SERVICE
assert device_entry.entry_type is dr.DeviceEntryType.SERVICE
assert device_entry.configuration_url == "https://www.twentemilieu.nl"
assert not device_entry.model
assert not device_entry.sw_version

View File

@ -484,7 +484,7 @@ async def test_loading_saving_data(hass, registry, area_registry):
model="via",
name="Original Name",
sw_version="Orig SW 1",
entry_type="device",
entry_type=None,
)
orig_light = registry.async_get_or_create(

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

@ -0,0 +1,35 @@
"""Test Home Assistant enum utils."""
from enum import auto
import pytest
from homeassistant.util.enum import StrEnum
def test_strenum():
"""Test StrEnum."""
class TestEnum(StrEnum):
Test = "test"
assert str(TestEnum.Test) == "test"
assert TestEnum.Test == "test"
assert TestEnum("test") is TestEnum.Test
assert TestEnum(TestEnum.Test) is TestEnum.Test
with pytest.raises(ValueError):
TestEnum(42)
with pytest.raises(ValueError):
TestEnum("str but unknown")
with pytest.raises(TypeError):
class FailEnum(StrEnum):
Test = 42
with pytest.raises(TypeError):
class FailEnum2(StrEnum):
Test = auto()