Skip to content

Commit

Permalink
Avoid checking for polling if an entity fails to add (#115159)
Browse files Browse the repository at this point in the history
* Avoid checking for polling if an entity fails to add

* no need to do protected access

* no need to do protected access

* no need to do protected access

* no need to do protected access

* coverage

* fix test

* fix

* broken one must be first
  • Loading branch information
bdraco authored and frenck committed Apr 8, 2024
1 parent d062ef3 commit 9a342f8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
11 changes: 10 additions & 1 deletion homeassistant/helpers/entity_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,16 @@ async def async_add_entities(
if (
(self.config_entry and self.config_entry.pref_disable_polling)
or self._async_unsub_polling is not None
or not any(entity.should_poll for entity in entities)
or not any(
# Entity may have failed to add or called `add_to_platform_abort`
# so we check if the entity is in self.entities before
# checking `entity.should_poll` since `should_poll` may need to
# check `self.hass` which will be `None` if the entity did not add
entity.entity_id
and entity.entity_id in self.entities
and entity.should_poll
for entity in entities
)
):
return

Expand Down
36 changes: 35 additions & 1 deletion tests/helpers/test_entity_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from datetime import timedelta
import logging
from typing import Any
from unittest.mock import ANY, Mock, patch
from unittest.mock import ANY, AsyncMock, Mock, patch

import pytest

Expand Down Expand Up @@ -78,6 +78,40 @@ async def test_polling_only_updates_entities_it_should_poll(
assert poll_ent.async_update.called


async def test_polling_check_works_if_entity_add_fails(
hass: HomeAssistant,
) -> None:
"""Test the polling check works if an entity add fails."""
component = EntityComponent(_LOGGER, DOMAIN, hass, timedelta(seconds=20))
await component.async_setup({})

class MockEntityNeedsSelfHassInShouldPoll(MockEntity):
"""Mock entity that needs self.hass in should_poll."""

@property
def should_poll(self) -> bool:
"""Return True if entity has to be polled."""
return self.hass.data is not None

working_poll_ent = MockEntityNeedsSelfHassInShouldPoll(should_poll=True)
working_poll_ent.async_update = AsyncMock()
broken_poll_ent = MockEntityNeedsSelfHassInShouldPoll(should_poll=True)
broken_poll_ent.async_update = AsyncMock(side_effect=Exception("Broken"))

await component.async_add_entities(
[broken_poll_ent, working_poll_ent], update_before_add=True
)

working_poll_ent.async_update.reset_mock()
broken_poll_ent.async_update.reset_mock()

async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=20))
await hass.async_block_till_done(wait_background_tasks=True)

assert not broken_poll_ent.async_update.called
assert working_poll_ent.async_update.called


async def test_polling_disabled_by_config_entry(hass: HomeAssistant) -> None:
"""Test the polling of only updated entities."""
entity_platform = MockEntityPlatform(hass)
Expand Down

0 comments on commit 9a342f8

Please sign in to comment.