diff --git a/homeassistant/components/renault/__init__.py b/homeassistant/components/renault/__init__.py index 4b7ff8f5648..1751225f987 100644 --- a/homeassistant/components/renault/__init__.py +++ b/homeassistant/components/renault/__init__.py @@ -15,6 +15,7 @@ from .renault_hub import RenaultHub from .services import setup_services CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) +RenaultConfigEntry = ConfigEntry[RenaultHub] async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: @@ -23,7 +24,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: return True -async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: +async def async_setup_entry( + hass: HomeAssistant, config_entry: RenaultConfigEntry +) -> bool: """Load a config entry.""" renault_hub = RenaultHub(hass, config_entry.data[CONF_LOCALE]) try: @@ -36,19 +39,20 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b if not login_success: raise ConfigEntryAuthFailed - hass.data.setdefault(DOMAIN, {}) try: await renault_hub.async_initialise(config_entry) except aiohttp.ClientError as exc: raise ConfigEntryNotReady from exc - hass.data[DOMAIN][config_entry.entry_id] = renault_hub + config_entry.runtime_data = renault_hub await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) return True -async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: +async def async_unload_entry( + hass: HomeAssistant, config_entry: RenaultConfigEntry +) -> bool: """Unload a config entry.""" return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS) diff --git a/homeassistant/components/renault/binary_sensor.py b/homeassistant/components/renault/binary_sensor.py index 37e91a1e435..2041499b711 100644 --- a/homeassistant/components/renault/binary_sensor.py +++ b/homeassistant/components/renault/binary_sensor.py @@ -12,14 +12,12 @@ from homeassistant.components.binary_sensor import ( BinarySensorEntity, BinarySensorEntityDescription, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType -from .const import DOMAIN +from . import RenaultConfigEntry from .entity import RenaultDataEntity, RenaultDataEntityDescription -from .renault_hub import RenaultHub @dataclass(frozen=True, kw_only=True) @@ -35,14 +33,13 @@ class RenaultBinarySensorEntityDescription( async def async_setup_entry( hass: HomeAssistant, - config_entry: ConfigEntry, + config_entry: RenaultConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Renault entities from config entry.""" - proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id] entities: list[RenaultBinarySensor] = [ RenaultBinarySensor(vehicle, description) - for vehicle in proxy.vehicles.values() + for vehicle in config_entry.runtime_data.vehicles.values() for description in BINARY_SENSOR_TYPES if description.coordinator in vehicle.coordinators ] diff --git a/homeassistant/components/renault/button.py b/homeassistant/components/renault/button.py index 9a6e1d76df6..d3666388fbb 100644 --- a/homeassistant/components/renault/button.py +++ b/homeassistant/components/renault/button.py @@ -7,13 +7,11 @@ from dataclasses import dataclass from typing import Any from homeassistant.components.button import ButtonEntity, ButtonEntityDescription -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import RenaultConfigEntry from .entity import RenaultEntity -from .renault_hub import RenaultHub @dataclass(frozen=True, kw_only=True) @@ -26,14 +24,13 @@ class RenaultButtonEntityDescription(ButtonEntityDescription): async def async_setup_entry( hass: HomeAssistant, - config_entry: ConfigEntry, + config_entry: RenaultConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Renault entities from config entry.""" - proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id] entities: list[RenaultButtonEntity] = [ RenaultButtonEntity(vehicle, description) - for vehicle in proxy.vehicles.values() + for vehicle in config_entry.runtime_data.vehicles.values() for description in BUTTON_TYPES if not description.requires_electricity or vehicle.details.uses_electricity() ] diff --git a/homeassistant/components/renault/device_tracker.py b/homeassistant/components/renault/device_tracker.py index 922173461a0..db889868cae 100644 --- a/homeassistant/components/renault/device_tracker.py +++ b/homeassistant/components/renault/device_tracker.py @@ -5,25 +5,22 @@ from __future__ import annotations from renault_api.kamereon.models import KamereonVehicleLocationData from homeassistant.components.device_tracker import SourceType, TrackerEntity -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from . import RenaultConfigEntry from .entity import RenaultDataEntity, RenaultDataEntityDescription -from .renault_hub import RenaultHub async def async_setup_entry( hass: HomeAssistant, - config_entry: ConfigEntry, + config_entry: RenaultConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Renault entities from config entry.""" - proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id] entities: list[RenaultDeviceTracker] = [ RenaultDeviceTracker(vehicle, description) - for vehicle in proxy.vehicles.values() + for vehicle in config_entry.runtime_data.vehicles.values() for description in DEVICE_TRACKER_TYPES if description.coordinator in vehicle.coordinators ] diff --git a/homeassistant/components/renault/diagnostics.py b/homeassistant/components/renault/diagnostics.py index 1234def019e..5d1849f4b20 100644 --- a/homeassistant/components/renault/diagnostics.py +++ b/homeassistant/components/renault/diagnostics.py @@ -5,13 +5,12 @@ from __future__ import annotations from typing import Any from homeassistant.components.diagnostics import async_redact_data -from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceEntry -from . import RenaultHub -from .const import CONF_KAMEREON_ACCOUNT_ID, DOMAIN +from . import RenaultConfigEntry +from .const import CONF_KAMEREON_ACCOUNT_ID from .renault_vehicle import RenaultVehicleProxy TO_REDACT = { @@ -27,11 +26,9 @@ TO_REDACT = { async def async_get_config_entry_diagnostics( - hass: HomeAssistant, entry: ConfigEntry + hass: HomeAssistant, entry: RenaultConfigEntry ) -> dict[str, Any]: """Return diagnostics for a config entry.""" - renault_hub: RenaultHub = hass.data[DOMAIN][entry.entry_id] - return { "entry": { "title": entry.title, @@ -39,18 +36,17 @@ async def async_get_config_entry_diagnostics( }, "vehicles": [ _get_vehicle_diagnostics(vehicle) - for vehicle in renault_hub.vehicles.values() + for vehicle in entry.runtime_data.vehicles.values() ], } async def async_get_device_diagnostics( - hass: HomeAssistant, entry: ConfigEntry, device: DeviceEntry + hass: HomeAssistant, entry: RenaultConfigEntry, device: DeviceEntry ) -> dict[str, Any]: """Return diagnostics for a device.""" - renault_hub: RenaultHub = hass.data[DOMAIN][entry.entry_id] vin = next(iter(device.identifiers))[1] - vehicle = renault_hub.vehicles[vin] + vehicle = entry.runtime_data.vehicles[vin] return _get_vehicle_diagnostics(vehicle) diff --git a/homeassistant/components/renault/select.py b/homeassistant/components/renault/select.py index eb79e197937..b430da9396e 100644 --- a/homeassistant/components/renault/select.py +++ b/homeassistant/components/renault/select.py @@ -8,14 +8,12 @@ from typing import cast from renault_api.kamereon.models import KamereonVehicleBatteryStatusData from homeassistant.components.select import SelectEntity, SelectEntityDescription -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType -from .const import DOMAIN +from . import RenaultConfigEntry from .entity import RenaultDataEntity, RenaultDataEntityDescription -from .renault_hub import RenaultHub @dataclass(frozen=True, kw_only=True) @@ -29,14 +27,13 @@ class RenaultSelectEntityDescription( async def async_setup_entry( hass: HomeAssistant, - config_entry: ConfigEntry, + config_entry: RenaultConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Renault entities from config entry.""" - proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id] entities: list[RenaultSelectEntity] = [ RenaultSelectEntity(vehicle, description) - for vehicle in proxy.vehicles.values() + for vehicle in config_entry.runtime_data.vehicles.values() for description in SENSOR_TYPES if description.coordinator in vehicle.coordinators ] diff --git a/homeassistant/components/renault/sensor.py b/homeassistant/components/renault/sensor.py index 352fddb8d8b..5cb4ee333cc 100644 --- a/homeassistant/components/renault/sensor.py +++ b/homeassistant/components/renault/sensor.py @@ -21,7 +21,6 @@ from homeassistant.components.sensor import ( SensorEntityDescription, SensorStateClass, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( PERCENTAGE, UnitOfEnergy, @@ -36,10 +35,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from homeassistant.util.dt import as_utc, parse_datetime -from .const import DOMAIN +from . import RenaultConfigEntry from .coordinator import T from .entity import RenaultDataEntity, RenaultDataEntityDescription -from .renault_hub import RenaultHub from .renault_vehicle import RenaultVehicleProxy @@ -58,14 +56,13 @@ class RenaultSensorEntityDescription( async def async_setup_entry( hass: HomeAssistant, - config_entry: ConfigEntry, + config_entry: RenaultConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Renault entities from config entry.""" - proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id] entities: list[RenaultSensor[Any]] = [ description.entity_class(vehicle, description) - for vehicle in proxy.vehicles.values() + for vehicle in config_entry.runtime_data.vehicles.values() for description in SENSOR_TYPES if description.coordinator in vehicle.coordinators and (not description.requires_fuel or vehicle.details.uses_fuel()) diff --git a/homeassistant/components/renault/services.py b/homeassistant/components/renault/services.py index c274e75b380..e02a0febdf2 100644 --- a/homeassistant/components/renault/services.py +++ b/homeassistant/components/renault/services.py @@ -9,13 +9,16 @@ from typing import TYPE_CHECKING, Any import voluptuous as vol +from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.helpers import config_validation as cv, device_registry as dr from .const import DOMAIN -from .renault_hub import RenaultHub from .renault_vehicle import RenaultVehicleProxy +if TYPE_CHECKING: + from . import RenaultConfigEntry + LOGGER = logging.getLogger(__name__) ATTR_SCHEDULES = "schedules" @@ -116,9 +119,13 @@ def setup_services(hass: HomeAssistant) -> None: if device_entry is None: raise ValueError(f"Unable to find device with id: {device_id}") - proxy: RenaultHub - for proxy in hass.data[DOMAIN].values(): - for vin, vehicle in proxy.vehicles.items(): + loaded_entries: list[RenaultConfigEntry] = [ + entry + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.state == ConfigEntryState.LOADED + ] + for entry in loaded_entries: + for vin, vehicle in entry.runtime_data.vehicles.items(): if (DOMAIN, vin) in device_entry.identifiers: return vehicle raise ValueError(f"Unable to find vehicle with VIN: {device_entry.identifiers}") diff --git a/tests/components/renault/test_init.py b/tests/components/renault/test_init.py index 6f222c760a7..e6c55f99810 100644 --- a/tests/components/renault/test_init.py +++ b/tests/components/renault/test_init.py @@ -57,7 +57,6 @@ async def test_setup_entry_bad_password( assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert config_entry.state is ConfigEntryState.SETUP_ERROR - assert not hass.data.get(DOMAIN) @pytest.mark.parametrize("side_effect", [aiohttp.ClientConnectionError, GigyaException]) @@ -76,7 +75,6 @@ async def test_setup_entry_exception( assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert config_entry.state is ConfigEntryState.SETUP_RETRY - assert not hass.data.get(DOMAIN) @pytest.mark.usefixtures("patch_renault_account") @@ -95,7 +93,6 @@ async def test_setup_entry_kamereon_exception( assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert config_entry.state is ConfigEntryState.SETUP_RETRY - assert not hass.data.get(DOMAIN) @pytest.mark.usefixtures("patch_renault_account", "patch_get_vehicles") @@ -111,4 +108,3 @@ async def test_setup_entry_missing_vehicle_details( assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert config_entry.state is ConfigEntryState.SETUP_RETRY - assert not hass.data.get(DOMAIN)