-
Notifications
You must be signed in to change notification settings - Fork 71
Log unique ID conflicts #683
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
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -976,6 +976,51 @@ def _discover_new_entities(self) -> None: | |
| entity.on_add() | ||
| self._pending_entities.append(entity) | ||
|
|
||
| @staticmethod | ||
| def _entity_class_path(entity: BaseEntity) -> tuple[str, str]: | ||
| """Return module and class name for an entity.""" | ||
| return (entity.__class__.__module__, entity.__class__.__name__) | ||
|
|
||
| @staticmethod | ||
| def _entity_endpoint_id(entity: BaseEntity) -> int | None: | ||
| """Return endpoint id if this is a platform entity.""" | ||
| if not isinstance(entity, PlatformEntity): | ||
| return None | ||
| return entity.endpoint.id | ||
|
|
||
| @staticmethod | ||
| def _entity_cluster_handler_names(entity: BaseEntity) -> list[str]: | ||
| """Return cluster handler names if this is a platform entity.""" | ||
| if not isinstance(entity, PlatformEntity): | ||
| return [] | ||
| return sorted(entity.cluster_handlers.keys()) | ||
|
|
||
| def _log_entity_unique_id_conflict( | ||
| self, | ||
| key: tuple[Platform, str], | ||
| existing_entity: BaseEntity, | ||
| duplicate_entity: BaseEntity, | ||
| ) -> None: | ||
| """Log duplicate unique_id collisions when classes differ.""" | ||
| existing_class = self._entity_class_path(existing_entity) | ||
| duplicate_class = self._entity_class_path(duplicate_entity) | ||
| if existing_class == duplicate_class: | ||
| return | ||
|
|
||
| _LOGGER.warning( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggestion: gate on a per-device # in __init__:
self._logged_unique_id_conflicts: set[tuple[Platform, str]] = set()
# in _log_entity_unique_id_conflict, after the class-equality check:
if key in self._logged_unique_id_conflicts:
return
self._logged_unique_id_conflicts.add(key) |
||
| "Entity unique_id conflict on device %s for %s: keeping %s " | ||
| "(endpoint=%s, cluster_handlers=%s), dropping %s " | ||
| "(endpoint=%s, cluster_handlers=%s)", | ||
| self.ieee, | ||
| key, | ||
| ".".join(existing_class), | ||
| self._entity_endpoint_id(existing_entity), | ||
| self._entity_cluster_handler_names(existing_entity), | ||
| ".".join(duplicate_class), | ||
| self._entity_endpoint_id(duplicate_entity), | ||
| self._entity_cluster_handler_names(duplicate_entity), | ||
| ) | ||
|
|
||
| async def async_initialize(self, from_cache: bool = False) -> None: | ||
| """Initialize cluster handlers.""" | ||
| self.debug("started initialization") | ||
|
|
@@ -1012,6 +1057,7 @@ async def async_initialize(self, from_cache: bool = False) -> None: | |
|
|
||
| # Ignore entities that already exist | ||
| if key in new_entities: | ||
| self._log_entity_unique_id_conflict(key, new_entities[key], entity) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth confirming in the PR body: this is intentionally surface-the-bug logging, not a fix. The duplicate |
||
| await entity.on_remove() | ||
| continue | ||
|
|
||
|
|
||
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.
existing_entity/duplicate_entitytyped asBaseEntitybut the call site (line 1060) only ever passesPlatformEntity—new_entitiesisdict[tuple[Platform, str], PlatformEntity]andentityreached this point viaentity.PLATFORM/entity.unique_id. Theisinstance(entity, PlatformEntity)guards in_entity_endpoint_id/_entity_cluster_handler_namesare dead branches.Either narrow these to
PlatformEntityand drop the guards (cleaner), or leave the guards in and add a comment explaining the future use case. Current shape is type-annotation overhead with no payoff.