Remove Nest code related to Works with Nest API removal (#130785)

This commit is contained in:
Allen Porter 2024-11-16 20:07:00 -08:00 committed by GitHub
parent d8dd6d6abe
commit b64f33e1d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 33 additions and 170 deletions

View File

@ -49,7 +49,6 @@ from homeassistant.helpers import (
config_validation as cv, config_validation as cv,
device_registry as dr, device_registry as dr,
entity_registry as er, entity_registry as er,
issue_registry as ir,
) )
from homeassistant.helpers.entity_registry import async_entries_for_device from homeassistant.helpers.entity_registry import async_entries_for_device
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
@ -119,20 +118,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
hass.http.register_view(NestEventMediaView(hass)) hass.http.register_view(NestEventMediaView(hass))
hass.http.register_view(NestEventMediaThumbnailView(hass)) hass.http.register_view(NestEventMediaThumbnailView(hass))
if DOMAIN in config and CONF_PROJECT_ID not in config[DOMAIN]:
ir.async_create_issue(
hass,
DOMAIN,
"legacy_nest_deprecated",
breaks_in_ha_version="2023.8.0",
is_fixable=False,
severity=ir.IssueSeverity.WARNING,
translation_key="legacy_nest_removed",
translation_placeholders={
"documentation_url": "https://www.home-assistant.io/integrations/nest/",
},
)
return False
return True return True

View File

@ -84,12 +84,6 @@
"doorbell_chime": "Doorbell pressed" "doorbell_chime": "Doorbell pressed"
} }
}, },
"issues": {
"legacy_nest_removed": {
"title": "Legacy Works With Nest has been removed",
"description": "Legacy Works With Nest has been removed from Home Assistant, and the API shuts down as of September 2023.\n\nYou must take action to use the SDM API. Remove all `nest` configuration from `configuration.yaml` and restart Home Assistant, then see the Nest [integration instructions]({documentation_url}) for set up instructions and supported devices."
}
},
"entity": { "entity": {
"event": { "event": {
"chime": { "chime": {

View File

@ -4,8 +4,7 @@ from __future__ import annotations
from collections.abc import Awaitable, Callable, Generator from collections.abc import Awaitable, Callable, Generator
import copy import copy
from dataclasses import dataclass, field from dataclasses import dataclass
import time
from typing import Any from typing import Any
from google_nest_sdm.auth import AbstractAuth from google_nest_sdm.auth import AbstractAuth
@ -37,7 +36,6 @@ SUBSCRIPTION_NAME = "projects/cloud-id-9876/subscriptions/subscriber-id-9876"
class NestTestConfig: class NestTestConfig:
"""Holder for integration configuration.""" """Holder for integration configuration."""
config: dict[str, Any] = field(default_factory=dict)
config_entry_data: dict[str, Any] | None = None config_entry_data: dict[str, Any] | None = None
credential: ClientCredential | None = None credential: ClientCredential | None = None
@ -54,39 +52,9 @@ TEST_CONFIG_APP_CREDS = NestTestConfig(
credential=ClientCredential(CLIENT_ID, CLIENT_SECRET), credential=ClientCredential(CLIENT_ID, CLIENT_SECRET),
) )
TEST_CONFIGFLOW_APP_CREDS = NestTestConfig( TEST_CONFIGFLOW_APP_CREDS = NestTestConfig(
config=TEST_CONFIG_APP_CREDS.config,
credential=ClientCredential(CLIENT_ID, CLIENT_SECRET), credential=ClientCredential(CLIENT_ID, CLIENT_SECRET),
) )
TEST_CONFIG_LEGACY = NestTestConfig(
config={
"nest": {
"client_id": "some-client-id",
"client_secret": "some-client-secret",
},
},
config_entry_data={
"auth_implementation": "local",
"tokens": {
"expires_at": time.time() + 86400,
"access_token": {
"token": "some-token",
},
},
},
)
TEST_CONFIG_ENTRY_LEGACY = NestTestConfig(
config_entry_data={
"auth_implementation": "local",
"tokens": {
"expires_at": time.time() + 86400,
"access_token": {
"token": "some-token",
},
},
},
)
TEST_CONFIG_NEW_SUBSCRIPTION = NestTestConfig( TEST_CONFIG_NEW_SUBSCRIPTION = NestTestConfig(
config_entry_data={ config_entry_data={
"sdm": {}, "sdm": {},

View File

@ -202,20 +202,6 @@ def nest_test_config() -> NestTestConfig:
return TEST_CONFIG_APP_CREDS return TEST_CONFIG_APP_CREDS
@pytest.fixture
def config(
subscriber_id: str | None, nest_test_config: NestTestConfig
) -> dict[str, Any]:
"""Fixture that sets up the configuration.yaml for the test."""
config = copy.deepcopy(nest_test_config.config)
if CONF_SUBSCRIBER_ID in config.get(DOMAIN, {}):
if subscriber_id:
config[DOMAIN][CONF_SUBSCRIBER_ID] = subscriber_id
else:
del config[DOMAIN][CONF_SUBSCRIBER_ID]
return config
@pytest.fixture @pytest.fixture
def config_entry_unique_id() -> str: def config_entry_unique_id() -> str:
"""Fixture to set ConfigEntry unique id.""" """Fixture to set ConfigEntry unique id."""
@ -275,20 +261,18 @@ async def credential(hass: HomeAssistant, nest_test_config: NestTestConfig) -> N
async def setup_base_platform( async def setup_base_platform(
hass: HomeAssistant, hass: HomeAssistant,
platforms: list[str], platforms: list[str],
config: dict[str, Any],
config_entry: MockConfigEntry | None, config_entry: MockConfigEntry | None,
) -> YieldFixture[PlatformSetup]: ) -> YieldFixture[PlatformSetup]:
"""Fixture to setup the integration platform.""" """Fixture to setup the integration platform."""
if config_entry: config_entry.add_to_hass(hass)
config_entry.add_to_hass(hass)
with patch("homeassistant.components.nest.PLATFORMS", platforms): with patch("homeassistant.components.nest.PLATFORMS", platforms):
async def _setup_func() -> bool: async def _setup_func() -> bool:
assert await async_setup_component(hass, DOMAIN, config) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
yield _setup_func yield _setup_func
if config_entry and config_entry.state == ConfigEntryState.LOADED: if config_entry.state == ConfigEntryState.LOADED:
await hass.config_entries.async_unload(config_entry.entry_id) await hass.config_entries.async_unload(config_entry.entry_id)

View File

@ -27,7 +27,6 @@ from .common import (
TEST_CONFIGFLOW_APP_CREDS, TEST_CONFIGFLOW_APP_CREDS,
FakeSubscriber, FakeSubscriber,
NestTestConfig, NestTestConfig,
PlatformSetup,
) )
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -350,11 +349,11 @@ def mock_pubsub_api_responses(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_app_credentials( async def test_app_credentials(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Check full flow.""" """Check full flow."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -389,12 +388,8 @@ async def test_app_credentials(
("sdm_managed_topic", "device_access_project_id", "cloud_project_id"), ("sdm_managed_topic", "device_access_project_id", "cloud_project_id"),
[(True, "new-project-id", "new-cloud-project-id")], [(True, "new-project-id", "new-cloud-project-id")],
) )
async def test_config_flow_restart( async def test_config_flow_restart(hass: HomeAssistant, oauth, subscriber) -> None:
hass: HomeAssistant, oauth, subscriber, setup_platform
) -> None:
"""Check with auth implementation is re-initialized when aborting the flow.""" """Check with auth implementation is re-initialized when aborting the flow."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -447,11 +442,11 @@ async def test_config_flow_restart(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_config_flow_wrong_project_id( async def test_config_flow_wrong_project_id(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Check the case where the wrong project ids are entered.""" """Check the case where the wrong project ids are entered."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -506,12 +501,9 @@ async def test_config_flow_wrong_project_id(
async def test_config_flow_pubsub_configuration_error( async def test_config_flow_pubsub_configuration_error(
hass: HomeAssistant, hass: HomeAssistant,
oauth, oauth,
setup_platform,
mock_subscriber, mock_subscriber,
) -> None: ) -> None:
"""Check full flow fails with configuration error.""" """Check full flow fails with configuration error."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -554,11 +546,9 @@ async def test_config_flow_pubsub_configuration_error(
[(True, HTTPStatus.INTERNAL_SERVER_ERROR)], [(True, HTTPStatus.INTERNAL_SERVER_ERROR)],
) )
async def test_config_flow_pubsub_subscriber_error( async def test_config_flow_pubsub_subscriber_error(
hass: HomeAssistant, oauth, setup_platform, mock_subscriber hass: HomeAssistant, oauth, mock_subscriber
) -> None: ) -> None:
"""Check full flow with a subscriber error.""" """Check full flow with a subscriber error."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -707,11 +697,9 @@ async def test_reauth_multiple_config_entries(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_pubsub_subscription_strip_whitespace( async def test_pubsub_subscription_strip_whitespace(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant, oauth, subscriber
) -> None: ) -> None:
"""Check that project id has whitespace stripped on entry.""" """Check that project id has whitespace stripped on entry."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -742,11 +730,9 @@ async def test_pubsub_subscription_strip_whitespace(
[(True, HTTPStatus.UNAUTHORIZED)], [(True, HTTPStatus.UNAUTHORIZED)],
) )
async def test_pubsub_subscription_auth_failure( async def test_pubsub_subscription_auth_failure(
hass: HomeAssistant, oauth, setup_platform, mock_subscriber hass: HomeAssistant, oauth, mock_subscriber
) -> None: ) -> None:
"""Check flow that creates a pub/sub subscription.""" """Check flow that creates a pub/sub subscription."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -819,7 +805,7 @@ async def test_pubsub_subscriber_config_entry_reauth(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_config_entry_title_from_home( async def test_config_entry_title_from_home(
hass: HomeAssistant, oauth, setup_platform, subscriber hass: HomeAssistant, oauth, subscriber
) -> None: ) -> None:
"""Test that the Google Home name is used for the config entry title.""" """Test that the Google Home name is used for the config entry title."""
@ -837,8 +823,6 @@ async def test_config_entry_title_from_home(
) )
) )
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -864,7 +848,7 @@ async def test_config_entry_title_from_home(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_config_entry_title_multiple_homes( async def test_config_entry_title_multiple_homes(
hass: HomeAssistant, oauth, setup_platform, subscriber hass: HomeAssistant, oauth, subscriber
) -> None: ) -> None:
"""Test handling of multiple Google Homes authorized.""" """Test handling of multiple Google Homes authorized."""
@ -894,8 +878,6 @@ async def test_config_entry_title_multiple_homes(
) )
) )
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -911,11 +893,9 @@ async def test_config_entry_title_multiple_homes(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_title_failure_fallback( async def test_title_failure_fallback(
hass: HomeAssistant, oauth, setup_platform, mock_subscriber hass: HomeAssistant, oauth, mock_subscriber
) -> None: ) -> None:
"""Test exception handling when determining the structure names.""" """Test exception handling when determining the structure names."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -943,9 +923,7 @@ async def test_title_failure_fallback(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_structure_missing_trait( async def test_structure_missing_trait(hass: HomeAssistant, oauth, subscriber) -> None:
hass: HomeAssistant, oauth, setup_platform, subscriber
) -> None:
"""Test handling the case where a structure has no name set.""" """Test handling the case where a structure has no name set."""
device_manager = await subscriber.async_get_device_manager() device_manager = await subscriber.async_get_device_manager()
@ -959,8 +937,6 @@ async def test_structure_missing_trait(
) )
) )
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -996,11 +972,11 @@ async def test_dhcp_discovery(
@pytest.mark.parametrize(("sdm_managed_topic"), [(True)]) @pytest.mark.parametrize(("sdm_managed_topic"), [(True)])
async def test_dhcp_discovery_with_creds( async def test_dhcp_discovery_with_creds(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Exercise discovery dhcp with no config present (can't run).""" """Exercise discovery dhcp with no config present (can't run)."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, DOMAIN,
context={"source": config_entries.SOURCE_DHCP}, context={"source": config_entries.SOURCE_DHCP},
@ -1054,13 +1030,10 @@ async def test_token_error(
hass: HomeAssistant, hass: HomeAssistant,
oauth: OAuthFixture, oauth: OAuthFixture,
subscriber: FakeSubscriber, subscriber: FakeSubscriber,
setup_platform: PlatformSetup,
status_code: HTTPStatus, status_code: HTTPStatus,
error_reason: str, error_reason: str,
) -> None: ) -> None:
"""Check full flow.""" """Check full flow."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -1090,11 +1063,11 @@ async def test_token_error(
], ],
) )
async def test_existing_topic_and_subscription( async def test_existing_topic_and_subscription(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Test selecting existing user managed topic and subscription.""" """Test selecting existing user managed topic and subscription."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -1129,11 +1102,11 @@ async def test_existing_topic_and_subscription(
async def test_no_eligible_topics( async def test_no_eligible_topics(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Test the case where there are no eligible pub/sub topics.""" """Test the case where there are no eligible pub/sub topics."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -1153,11 +1126,11 @@ async def test_no_eligible_topics(
], ],
) )
async def test_list_topics_failure( async def test_list_topics_failure(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Test selecting existing user managed topic and subscription.""" """Test selecting existing user managed topic and subscription."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
@ -1177,11 +1150,11 @@ async def test_list_topics_failure(
], ],
) )
async def test_list_subscriptions_failure( async def test_list_subscriptions_failure(
hass: HomeAssistant, oauth, subscriber, setup_platform hass: HomeAssistant,
oauth,
subscriber,
) -> None: ) -> None:
"""Test selecting existing user managed topic and subscription.""" """Test selecting existing user managed topic and subscription."""
await setup_platform()
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )

View File

@ -24,22 +24,16 @@ import pytest
from homeassistant.components.nest import DOMAIN from homeassistant.components.nest import DOMAIN
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .common import ( from .common import (
PROJECT_ID, PROJECT_ID,
SUBSCRIBER_ID, SUBSCRIBER_ID,
TEST_CONFIG_ENTRY_LEGACY,
TEST_CONFIG_LEGACY,
TEST_CONFIG_NEW_SUBSCRIPTION, TEST_CONFIG_NEW_SUBSCRIPTION,
TEST_CONFIGFLOW_APP_CREDS,
FakeSubscriber, FakeSubscriber,
PlatformSetup, PlatformSetup,
YieldFixture, YieldFixture,
) )
from tests.common import MockConfigEntry
PLATFORM = "sensor" PLATFORM = "sensor"
@ -201,18 +195,6 @@ async def test_subscriber_configuration_failure(
assert entries[0].state is ConfigEntryState.SETUP_ERROR assert entries[0].state is ConfigEntryState.SETUP_ERROR
@pytest.mark.parametrize("nest_test_config", [TEST_CONFIGFLOW_APP_CREDS])
async def test_empty_config(
hass: HomeAssistant, error_caplog: pytest.LogCaptureFixture, config, setup_platform
) -> None:
"""Test setup is a no-op with not config."""
await setup_platform()
assert not error_caplog.records
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 0
async def test_unload_entry(hass: HomeAssistant, setup_platform) -> None: async def test_unload_entry(hass: HomeAssistant, setup_platform) -> None:
"""Test successful unload of a ConfigEntry.""" """Test successful unload of a ConfigEntry."""
await setup_platform() await setup_platform()
@ -318,26 +300,3 @@ async def test_migrate_unique_id(
assert config_entry.state is ConfigEntryState.LOADED assert config_entry.state is ConfigEntryState.LOADED
assert config_entry.unique_id == PROJECT_ID assert config_entry.unique_id == PROJECT_ID
@pytest.mark.parametrize("nest_test_config", [TEST_CONFIG_LEGACY])
async def test_legacy_works_with_nest_yaml(
hass: HomeAssistant,
config: dict[str, Any],
config_entry: MockConfigEntry,
) -> None:
"""Test integration won't start with legacy works with nest yaml config."""
config_entry.add_to_hass(hass)
assert not await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
@pytest.mark.parametrize("nest_test_config", [TEST_CONFIG_ENTRY_LEGACY])
async def test_legacy_works_with_nest_cleanup(
hass: HomeAssistant, setup_platform
) -> None:
"""Test legacy works with nest config entries are silently removed once yaml is removed."""
await setup_platform()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 0