mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 01:37:08 +00:00
Add checks for config entry state in async_config_entry_first_refresh (#128148)
This commit is contained in:
parent
1ad3a96643
commit
e5a07da0c9
@ -293,6 +293,18 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]):
|
|||||||
error_if_core=True,
|
error_if_core=True,
|
||||||
error_if_integration=False,
|
error_if_integration=False,
|
||||||
)
|
)
|
||||||
|
elif (
|
||||||
|
self.config_entry.state
|
||||||
|
is not config_entries.ConfigEntryState.SETUP_IN_PROGRESS
|
||||||
|
):
|
||||||
|
report(
|
||||||
|
"uses `async_config_entry_first_refresh`, which is only supported "
|
||||||
|
f"when entry state is {config_entries.ConfigEntryState.SETUP_IN_PROGRESS}, "
|
||||||
|
f"but it is in state {self.config_entry.state}, "
|
||||||
|
"This will stop working in Home Assistant 2025.11",
|
||||||
|
error_if_core=True,
|
||||||
|
error_if_integration=False,
|
||||||
|
)
|
||||||
if await self.__wrap_async_setup():
|
if await self.__wrap_async_setup():
|
||||||
await self._async_refresh(
|
await self._async_refresh(
|
||||||
log_failures=False, raise_on_auth_failed=True, raise_on_entry_error=True
|
log_failures=False, raise_on_auth_failed=True, raise_on_entry_error=True
|
||||||
|
@ -8,6 +8,7 @@ from aioraven.device import RAVEnConnectionError
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.rainforest_raven.coordinator import RAVEnDataCoordinator
|
from homeassistant.components.rainforest_raven.coordinator import RAVEnDataCoordinator
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ from . import create_mock_entry
|
|||||||
async def test_coordinator_device_info(hass: HomeAssistant) -> None:
|
async def test_coordinator_device_info(hass: HomeAssistant) -> None:
|
||||||
"""Test reporting device information from the coordinator."""
|
"""Test reporting device information from the coordinator."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
assert coordinator.device_fw_version is None
|
assert coordinator.device_fw_version is None
|
||||||
@ -44,6 +46,7 @@ async def test_coordinator_cache_device(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test that the device isn't re-opened for subsequent refreshes."""
|
"""Test that the device isn't re-opened for subsequent refreshes."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
@ -60,6 +63,7 @@ async def test_coordinator_device_error_setup(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test handling of a device error during initialization."""
|
"""Test handling of a device error during initialization."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
mock_device.get_network_info.side_effect = RAVEnConnectionError
|
mock_device.get_network_info.side_effect = RAVEnConnectionError
|
||||||
@ -72,6 +76,7 @@ async def test_coordinator_device_error_update(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test handling of a device error during an update."""
|
"""Test handling of a device error during an update."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
@ -87,6 +92,7 @@ async def test_coordinator_device_timeout_update(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test handling of a device timeout during an update."""
|
"""Test handling of a device timeout during an update."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
@ -102,6 +108,7 @@ async def test_coordinator_comm_error(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test handling of an error parsing or reading raw device data."""
|
"""Test handling of an error parsing or reading raw device data."""
|
||||||
entry = create_mock_entry()
|
entry = create_mock_entry()
|
||||||
|
entry._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
coordinator = RAVEnDataCoordinator(hass, entry)
|
coordinator = RAVEnDataCoordinator(hass, entry)
|
||||||
|
|
||||||
mock_device.synchronize.side_effect = RAVEnConnectionError
|
mock_device.synchronize.side_effect = RAVEnConnectionError
|
||||||
|
@ -551,6 +551,9 @@ async def test_async_config_entry_first_refresh_failure(
|
|||||||
a decreasing level of logging once the first message is logged.
|
a decreasing level of logging once the first message is logged.
|
||||||
"""
|
"""
|
||||||
entry = MockConfigEntry()
|
entry = MockConfigEntry()
|
||||||
|
entry._async_set_state(
|
||||||
|
hass, config_entries.ConfigEntryState.SETUP_IN_PROGRESS, None
|
||||||
|
)
|
||||||
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
||||||
setattr(crd, method, AsyncMock(side_effect=err_msg[0]))
|
setattr(crd, method, AsyncMock(side_effect=err_msg[0]))
|
||||||
|
|
||||||
@ -586,6 +589,9 @@ async def test_async_config_entry_first_refresh_failure_passed_through(
|
|||||||
a decreasing level of logging once the first message is logged.
|
a decreasing level of logging once the first message is logged.
|
||||||
"""
|
"""
|
||||||
entry = MockConfigEntry()
|
entry = MockConfigEntry()
|
||||||
|
entry._async_set_state(
|
||||||
|
hass, config_entries.ConfigEntryState.SETUP_IN_PROGRESS, None
|
||||||
|
)
|
||||||
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
||||||
setattr(crd, method, AsyncMock(side_effect=err_msg[0]))
|
setattr(crd, method, AsyncMock(side_effect=err_msg[0]))
|
||||||
|
|
||||||
@ -600,6 +606,9 @@ async def test_async_config_entry_first_refresh_failure_passed_through(
|
|||||||
async def test_async_config_entry_first_refresh_success(hass: HomeAssistant) -> None:
|
async def test_async_config_entry_first_refresh_success(hass: HomeAssistant) -> None:
|
||||||
"""Test first refresh successfully."""
|
"""Test first refresh successfully."""
|
||||||
entry = MockConfigEntry()
|
entry = MockConfigEntry()
|
||||||
|
entry._async_set_state(
|
||||||
|
hass, config_entries.ConfigEntryState.SETUP_IN_PROGRESS, None
|
||||||
|
)
|
||||||
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
||||||
crd.setup_method = AsyncMock()
|
crd.setup_method = AsyncMock()
|
||||||
await crd.async_config_entry_first_refresh()
|
await crd.async_config_entry_first_refresh()
|
||||||
@ -608,6 +617,46 @@ async def test_async_config_entry_first_refresh_success(hass: HomeAssistant) ->
|
|||||||
crd.setup_method.assert_called_once()
|
crd.setup_method.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_config_entry_first_refresh_invalid_state(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
) -> None:
|
||||||
|
"""Test first refresh fails due to invalid state."""
|
||||||
|
entry = MockConfigEntry()
|
||||||
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
||||||
|
crd.setup_method = AsyncMock()
|
||||||
|
with pytest.raises(
|
||||||
|
RuntimeError,
|
||||||
|
match="Detected code that uses `async_config_entry_first_refresh`, which "
|
||||||
|
"is only supported when entry state is ConfigEntryState.SETUP_IN_PROGRESS, "
|
||||||
|
"but it is in state ConfigEntryState.NOT_LOADED. This will stop working "
|
||||||
|
"in Home Assistant 2025.11. Please report this issue.",
|
||||||
|
):
|
||||||
|
await crd.async_config_entry_first_refresh()
|
||||||
|
|
||||||
|
assert crd.last_update_success is True
|
||||||
|
crd.setup_method.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_integration_frame")
|
||||||
|
async def test_async_config_entry_first_refresh_invalid_state_in_integration(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test first refresh successfully, despite wrong state."""
|
||||||
|
entry = MockConfigEntry()
|
||||||
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, entry)
|
||||||
|
crd.setup_method = AsyncMock()
|
||||||
|
|
||||||
|
await crd.async_config_entry_first_refresh()
|
||||||
|
assert crd.last_update_success is True
|
||||||
|
crd.setup_method.assert_called()
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'hue' uses `async_config_entry_first_refresh`, which "
|
||||||
|
"is only supported when entry state is ConfigEntryState.SETUP_IN_PROGRESS, "
|
||||||
|
"but it is in state ConfigEntryState.NOT_LOADED, This will stop working "
|
||||||
|
"in Home Assistant 2025.11"
|
||||||
|
) in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_async_config_entry_first_refresh_no_entry(hass: HomeAssistant) -> None:
|
async def test_async_config_entry_first_refresh_no_entry(hass: HomeAssistant) -> None:
|
||||||
"""Test first refresh successfully."""
|
"""Test first refresh successfully."""
|
||||||
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, None)
|
crd = get_crd(hass, DEFAULT_UPDATE_INTERVAL, None)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user