From 413b74a2e018c7108100841c6cfa77311ffb19db Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 27 Feb 2024 11:36:36 +0100 Subject: [PATCH] Deprecate Logi Circle integration (#111491) * Deprecate Logi Circle integration * Update homeassistant/components/logi_circle/__init__.py Co-authored-by: G Johansson --------- Co-authored-by: G Johansson --- .../components/logi_circle/__init__.py | 22 +++++- .../components/logi_circle/strings.json | 6 ++ tests/components/logi_circle/test_init.py | 68 +++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/components/logi_circle/test_init.py diff --git a/homeassistant/components/logi_circle/__init__.py b/homeassistant/components/logi_circle/__init__.py index abdae4001f3..fa358d05fcd 100644 --- a/homeassistant/components/logi_circle/__init__.py +++ b/homeassistant/components/logi_circle/__init__.py @@ -22,7 +22,7 @@ from homeassistant.const import ( Platform, ) from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.helpers import config_validation as cv +from homeassistant.helpers import config_validation as cv, issue_registry as ir from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.typing import ConfigType @@ -131,6 +131,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Logi Circle from a config entry.""" + ir.async_create_issue( + hass, + DOMAIN, + DOMAIN, + breaks_in_ha_version="2024.9.0", + is_fixable=False, + severity=ir.IssueSeverity.WARNING, + translation_key="integration_removed", + translation_placeholders={ + "entries": "/config/integrations/integration/logi_circle", + }, + ) + logi_circle = LogiCircle( client_id=entry.data[CONF_CLIENT_ID], client_secret=entry.data[CONF_CLIENT_SECRET], @@ -239,6 +252,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" + if all( + config_entry.state is config_entries.ConfigEntryState.NOT_LOADED + for config_entry in hass.config_entries.async_entries(DOMAIN) + if config_entry.entry_id != entry.entry_id + ): + ir.async_delete_issue(hass, DOMAIN, DOMAIN) + unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) logi_circle = hass.data.pop(DATA_LOGI) diff --git a/homeassistant/components/logi_circle/strings.json b/homeassistant/components/logi_circle/strings.json index 188139e6c29..be0f4632c25 100644 --- a/homeassistant/components/logi_circle/strings.json +++ b/homeassistant/components/logi_circle/strings.json @@ -44,6 +44,12 @@ } } }, + "issues": { + "integration_removed": { + "title": "The Logi Circle integration has been deprecated and will be removed", + "description": "Logitech stopped accepting applications for access to the Logi Circle API in May 2022, and the Logi Circle integration will be removed from Home Assistant.\n\nTo resolve this issue, please remove the integration entries from your Home Assistant setup. [Click here to see your existing Logi Circle integration entries]({entries})." + } + }, "services": { "set_config": { "name": "Set config", diff --git a/tests/components/logi_circle/test_init.py b/tests/components/logi_circle/test_init.py new file mode 100644 index 00000000000..f8bf8306609 --- /dev/null +++ b/tests/components/logi_circle/test_init.py @@ -0,0 +1,68 @@ +"""Tests for the Logi Circle integration.""" + +import asyncio +from unittest.mock import AsyncMock, Mock, patch + +import pytest + +from homeassistant.components.logi_circle import DOMAIN +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant +from homeassistant.helpers import issue_registry as ir + +from tests.common import MockConfigEntry + + +@pytest.fixture(name="disable_platforms") +async def disable_platforms_fixture(hass): + """Disable logi_circle platforms.""" + with patch("homeassistant.components.logi_circle.PLATFORMS", []): + yield + + +@pytest.fixture +def mock_logi_circle(): + """Mock logi_circle.""" + + auth_provider_mock = Mock() + auth_provider_mock.close = AsyncMock() + auth_provider_mock.clear_authorization = AsyncMock() + + with patch("homeassistant.components.logi_circle.LogiCircle") as logi_circle: + future = asyncio.Future() + future.set_result({"accountId": "testId"}) + LogiCircle = logi_circle() + LogiCircle.auth_provider = auth_provider_mock + LogiCircle.synchronize_cameras = AsyncMock() + yield LogiCircle + + +async def test_repair_issue( + hass: HomeAssistant, + issue_registry: ir.IssueRegistry, + disable_platforms, + mock_logi_circle, +) -> None: + """Test the LogiCircle configuration entry loading/unloading handles the repair.""" + config_entry = MockConfigEntry( + title="Example 1", + domain=DOMAIN, + data={ + "api_key": "blah", + "client_id": "blah", + "client_secret": "blah", + "redirect_uri": "blah", + }, + ) + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.LOADED + assert issue_registry.async_get_issue(DOMAIN, DOMAIN) + + # Remove the entry + await hass.config_entries.async_remove(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.NOT_LOADED + assert issue_registry.async_get_issue(DOMAIN, DOMAIN) is None