From d96f71d9b89d1af80f8c22b08d4029a178196535 Mon Sep 17 00:00:00 2001 From: DanielV <daniel@vikstrom.name> Date: Tue, 22 Oct 2024 11:28:43 +0000 Subject: [PATCH] Rework migration code --- .gitignore | 3 +- .../nordpool_planner/__init__.py | 101 ++++++++++++------ 2 files changed, 68 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 8eddca8..1708713 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ www/ .HA_VERSION __pycache__ home-assistant* -/*.yaml \ No newline at end of file +/*.yaml +.coverage \ No newline at end of file diff --git a/custom_components/nordpool_planner/__init__.py b/custom_components/nordpool_planner/__init__.py index 7a552cf..49576c3 100644 --- a/custom_components/nordpool_planner/__init__.py +++ b/custom_components/nordpool_planner/__init__.py @@ -12,7 +12,7 @@ STATE_UNKNOWN, Platform, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, HomeAssistantError from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import ( @@ -81,60 +81,91 @@ async def async_reload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Migrate old entry.""" _LOGGER.debug( - "Migrating configuration from version %s.%s", + "Attempting migrating configuration from version %s.%s", config_entry.version, config_entry.minor_version, ) + + class MigrateError(HomeAssistantError): + """Error to indicate there is was an error in version migration.""" + installed_version = NordpoolPlannerConfigFlow.VERSION installed_minor_version = NordpoolPlannerConfigFlow.MINOR_VERSION + new_data = {**config_entry.data} + new_options = {**config_entry.options} + if config_entry.version > installed_version: - # Downgraded from a future version + _LOGGER.warning( + "Downgrading major version from %s to %s is not allowed", + config_entry.version, + installed_version, + ) return False - if config_entry.version == 1: - new_data = {**config_entry.data} - new_options = {**config_entry.options} + if ( + config_entry.version == installed_version + and config_entry.minor_version > installed_minor_version + ): + _LOGGER.warning( + "Downgrading minor version from %s.%s to %s.%s is not allowed", + config_entry.version, + config_entry.minor_version, + installed_version, + installed_minor_version, + ) + return False - np_entity = hass.states.get(new_data[CONF_PRICES_ENTITY]) + def options_1x_to_20(options: dict, data: dict, hass: HomeAssistant): try: + np_entity = hass.states.get(data[CONF_PRICES_ENTITY]) uom = np_entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT) - new_options.pop("currency") - new_options[ATTR_UNIT_OF_MEASUREMENT] = uom + options.pop("currency") + options[ATTR_UNIT_OF_MEASUREMENT] = uom + except (IndexError, KeyError) as err: + _LOGGER.warning("Could not extract currency from Prices entity") + raise MigrateError from err + return options + + def data_20_to_21(data: dict): + if entity_id := data.pop("np_entity"): + data[CONF_PRICES_ENTITY] = entity_id + return data + _LOGGER.warning('Could not find "np_entity" in config_entry') + raise MigrateError('Could not find "np_entity" in config_entry') - except (IndexError, KeyError): - _LOGGER.warning("Could not extract currency from Nordpool entity") + if config_entry.version == 1: + try: + # Version 1.x to 2.0 + new_options = options_1x_to_20(new_options, new_data, hass) + # Version 2.0 to 2.1 + new_data = data_20_to_21(new_data) + except MigrateError: + _LOGGER.warning("Error while upgrading from version 1.x to 2.1") return False - hass.config_entries.async_update_entry( - config_entry, - data=new_data, - options=new_options, - version=installed_version, - minor_version=installed_minor_version, - ) - if config_entry.version == 2 and config_entry.minor_version == 0: - new_data = {**config_entry.data} - new_options = {**config_entry.options} - - entity_id = new_data.pop("np_entity") - new_data[CONF_PRICES_ENTITY] = entity_id - - hass.config_entries.async_update_entry( - config_entry, - data=new_data, - options=new_options, - version=installed_version, - minor_version=installed_minor_version, - ) + try: + # Version 2.0 to 2.1 + new_data = data_20_to_21(new_data) + except MigrateError: + _LOGGER.warning("Error while upgrading from version 2.0 to 2.1") + return False - _LOGGER.debug( - "Migration to configuration version %s.%s successful", + hass.config_entries.async_update_entry( + config_entry, + data=new_data, + options=new_options, + version=installed_version, + minor_version=installed_minor_version, + ) + _LOGGER.info( + "Migration configuration from version %s.%s to %s.%s successful", config_entry.version, config_entry.minor_version, + installed_version, + installed_minor_version, ) - return True