-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keep overkiz unique ids stable for pyoverkiz >= 1.10.1 #99765
Conversation
With pyoverkiz >= 1.10.1 the library uses StrEnums that have a different string representation than the previously used Enums (enum value vs. enum class + option name). Keep using enum class + option name in order to ensure stable unique_ids. This fixes the problem that upgrading pyoverkiz would lead to new entities.
@@ -114,7 +115,12 @@ def __init__( | |||
"""Initialize the device.""" | |||
super().__init__(device_url, coordinator) | |||
self.entity_description = description | |||
self._attr_unique_id = f"{super().unique_id}-{self.entity_description.key}" | |||
|
|||
# Keep ids stable for pyoverkiz >= 1.10.1 where enums changed to StrEnum. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the comment is wrong, shouldn't it be like this?
# Keep ids stable for pyoverkiz >= 1.10.1 where enums changed to StrEnum. | |
# Keep ids stable for pyoverkiz >= 1.10.0 where enums changed to StrEnum. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. This needs to be 1.10.0
here and in the commit message. There's a chance that github would lose the discussion below if I change the commit in the PR. I'd therefore only do that in a later step if we go on with this PR.
unique_id_ext = self.entity_description.key | ||
if isinstance(unique_id_ext, StrEnum): | ||
unique_id_ext = f"{unique_id_ext.__class__.__name__}.{unique_id_ext.name}" | ||
self._attr_unique_id = f"{super().unique_id}-{unique_id_ext}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of this, can we rewrite unique IDs via a migration step?
Here's an example of how it can be done:
core/homeassistant/components/bmw_connected_drive/__init__.py
Lines 82 to 110 in 714fc53
@callback | |
def update_unique_id(entry: er.RegistryEntry) -> dict[str, str] | None: | |
replacements = { | |
"charging_level_hv": "remaining_battery_percent", | |
"fuel_percent": "remaining_fuel_percent", | |
} | |
if (key := entry.unique_id.split("-")[-1]) in replacements: | |
new_unique_id = entry.unique_id.replace(key, replacements[key]) | |
_LOGGER.debug( | |
"Migrating entity '%s' unique_id from '%s' to '%s'", | |
entry.entity_id, | |
entry.unique_id, | |
new_unique_id, | |
) | |
if existing_entity_id := entity_registry.async_get_entity_id( | |
entry.domain, entry.platform, new_unique_id | |
): | |
_LOGGER.debug( | |
"Cannot migrate to unique_id '%s', already exists for '%s'", | |
new_unique_id, | |
existing_entity_id, | |
) | |
return None | |
return { | |
"new_unique_id": new_unique_id, | |
} | |
return None | |
await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, this may be very tricky to get 100% correct, rewriting the unique_id as suggested in this PR is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emontnemery it sucks that we didn't catch this before Python 3.11 was added to HA (no tests in Overkiz is the main cause). The Python3.11 update had a breaking change in how (str, Enum) are handled. See https://blog.pecar.me/python-enum.
History:
< 2023.3: unique_id="io://XXXX-XXXX-XXXX/XXXXXXX-core:DiscreteRSSILevelState"
> 2023.3 (with Python 3.11): unique_id="io://XXXX-XXXX-XXXX/XXXXXXX-OverkizState.CORE_DISCRETE_RSSI_LEVEL"
2023.9.0 (move to StrEnum in pyOverkiz): unique_id="io://XXXX-XXXX-XXXX/XXXXXXX-core:DiscreteRSSILevelState"
2023.9.1 (revert pyOverkiz): unique_id="io://XXXX-XXXX-XXXX/XXXXXXX-OverkizState.CORE_DISCRETE_RSSI_LEVEL"
So by not catching it, we actually broke the entity registry multiple times for our users. This happens to entities that I am not actively using myself, thus I didn't spot it earlier. Would be good to fix it now once and for all and move back to the original unique id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First try to implement your suggestion: #101024.
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
PR #99742 reverted the library bump, this PR should include the bump too. |
Hey there @iMicknl, @vlebourl, @tetienne, @nyroDev, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
What do you think of that #99950 (comment) ? |
We can just add an alert to prevent users for 2023.9.0 breaking change and advice to skip .0 and go directly to 2023.9.1+ ! |
I still think we should clean this up as requested in #99404 (comment), I paste it here again: The issue will hurt everyone who upgraded to 2023.9.0, because they will now have duplicated overkiz entities, with the old entities' state set to "UNAVAILABLE". The duplicates added by 2023.9.0 will have a new entity ID meaning any automation etc. referencing them will no longer work. To properly fix this mess I think the following is needed:
|
I can't really decide if this PR or the |
Thanks @fetzerch, @Quentame and @emontnemery for working on this! I am back from holidays and will have a look at this issue. My preference would be to add a migration for this. It would be cleaner to have However, easiest would be to override What would be your preference? |
@fetzerch my proposal for now is https://github.com/home-assistant/core/pull/101024/files. Lets see if we can get this merged in. Feel free to test my fix. I will review your other PR's after this has been fixed, thanks for spotting the issue and thanks for your other contributions!! |
@iMicknl Commented on the other PR. Indeed, let's get your fix in first that's clearly the most important change. Shall we close this PR then? Or keep it open until yours is merged (for the history/discussion)? |
If you agree that the other way is preferred, lets close this PR. |
Proposed change
With pyoverkiz >= 1.10.1 the library uses StrEnums that have a different string representation than the previously used Enums (enum value vs. enum class + option name). Keep using enum class + option name in order to ensure stable unique_ids.
This fixes the problem that upgrading pyoverkiz would lead to new entities.
See iMicknl/python-overkiz-api#923 (comment) for a more detailed problem description.
Type of change
Additional information
Checklist
black --fast homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
..coveragerc
.To help with the load of incoming pull requests: