From 57efa9569c2bb744f167c4e07b0f7600702fc091 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 24 Jun 2022 17:05:36 -0400 Subject: [PATCH] Cache is_supported for Google entities (#73936) --- .../components/google_assistant/helpers.py | 13 ++++++- .../google_assistant/test_helpers.py | 35 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/google_assistant/helpers.py b/homeassistant/components/google_assistant/helpers.py index 2ed91b42ec6..932611390eb 100644 --- a/homeassistant/components/google_assistant/helpers.py +++ b/homeassistant/components/google_assistant/helpers.py @@ -90,6 +90,7 @@ class AbstractConfig(ABC): self._local_sdk_active = False self._local_last_active: datetime | None = None self._local_sdk_version_warn = False + self.is_supported_cache: dict[str, tuple[int | None, bool]] = {} async def async_initialize(self): """Perform async initialization of config.""" @@ -541,7 +542,17 @@ class GoogleEntity: @callback def is_supported(self) -> bool: """Return if the entity is supported by Google.""" - return bool(self.traits()) + features: int | None = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) + + result = self.config.is_supported_cache.get(self.entity_id) + + if result is None or result[0] != features: + result = self.config.is_supported_cache[self.entity_id] = ( + features, + bool(self.traits()), + ) + + return result[1] @callback def might_2fa(self) -> bool: diff --git a/tests/components/google_assistant/test_helpers.py b/tests/components/google_assistant/test_helpers.py index 1ab573baf2a..8898fc7ef76 100644 --- a/tests/components/google_assistant/test_helpers.py +++ b/tests/components/google_assistant/test_helpers.py @@ -327,7 +327,9 @@ async def test_sync_entities_all(agents, result): def test_supported_features_string(caplog): """Test bad supported features.""" entity = helpers.GoogleEntity( - None, None, State("test.entity_id", "on", {"supported_features": "invalid"}) + None, + MockConfig(), + State("test.entity_id", "on", {"supported_features": "invalid"}), ) assert entity.is_supported() is False assert "Entity test.entity_id contains invalid supported_features value invalid" @@ -427,3 +429,34 @@ async def test_config_local_sdk_warn_version(hass, hass_client, caplog, version) f"Local SDK version is too old ({version}), check documentation on how " "to update to the latest version" ) in caplog.text + + +def test_is_supported_cached(): + """Test is_supported is cached.""" + config = MockConfig() + + def entity(features: int): + return helpers.GoogleEntity( + None, + config, + State("test.entity_id", "on", {"supported_features": features}), + ) + + with patch( + "homeassistant.components.google_assistant.helpers.GoogleEntity.traits", + return_value=[1], + ) as mock_traits: + assert entity(1).is_supported() is True + assert len(mock_traits.mock_calls) == 1 + + # Supported feature changes, so we calculate again + assert entity(2).is_supported() is True + assert len(mock_traits.mock_calls) == 2 + + mock_traits.reset_mock() + + # Supported feature is same, so we do not calculate again + mock_traits.side_effect = ValueError + + assert entity(2).is_supported() is True + assert len(mock_traits.mock_calls) == 0