From daef62598519c98fc9abebd3db2f96ac62fab85f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 11 May 2024 16:47:17 +0900 Subject: [PATCH] Speed up init and finish flow (#117226) Since every flow now has to check for single config entry, change the check to see if a config entry exists first before calling the _support_single_config_entry_only since _support_single_config_entry_only has to load the integration which adds up quite a bit in test runs --- homeassistant/config_entries.py | 28 +++++++++++++++++++++------- tests/test_config_entries.py | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 8937eb32377..eed1c507869 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -1198,8 +1198,8 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager[ConfigFlowResult]): # a single config entry, but which already has an entry if ( context.get("source") not in {SOURCE_IGNORE, SOURCE_REAUTH, SOURCE_UNIGNORE} + and self.config_entries.async_has_entries(handler, include_ignore=False) and await _support_single_config_entry_only(self.hass, handler) - and self.config_entries.async_entries(handler, include_ignore=False) ): return ConfigFlowResult( type=data_entry_flow.FlowResultType.ABORT, @@ -1303,9 +1303,9 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager[ConfigFlowResult]): # Avoid adding a config entry for a integration # that only supports a single config entry, but already has an entry if ( - await _support_single_config_entry_only(self.hass, flow.handler) + self.config_entries.async_has_entries(flow.handler, include_ignore=False) + and await _support_single_config_entry_only(self.hass, flow.handler) and flow.context["source"] != SOURCE_IGNORE - and self.config_entries.async_entries(flow.handler, include_ignore=False) ): return ConfigFlowResult( type=data_entry_flow.FlowResultType.ABORT, @@ -1344,10 +1344,9 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager[ConfigFlowResult]): await flow.async_set_unique_id(None) # Find existing entry. - for check_entry in self.config_entries.async_entries(result["handler"]): - if check_entry.unique_id == flow.unique_id: - existing_entry = check_entry - break + existing_entry = self.config_entries.async_entry_for_domain_unique_id( + result["handler"], flow.unique_id + ) # Unload the entry before setting up the new one. # We will remove it only after the other one is set up, @@ -1574,6 +1573,21 @@ class ConfigEntries: """Return entry ids.""" return list(self._entries.data) + @callback + def async_has_entries( + self, domain: str, include_ignore: bool = True, include_disabled: bool = True + ) -> bool: + """Return if there are entries for a domain.""" + entries = self._entries.get_entries_for_domain(domain) + if include_ignore and include_disabled: + return bool(entries) + return any( + entry + for entry in entries + if (include_ignore or entry.source != SOURCE_IGNORE) + and (include_disabled or not entry.disabled_by) + ) + @callback def async_entries( self, diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index f52dd8cceb9..c23cf4b1ac4 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -692,6 +692,13 @@ async def test_entries_excludes_ignore_and_disabled( entry3, disabled_entry, ] + assert manager.async_has_entries("test") is True + assert manager.async_has_entries("test2") is True + assert manager.async_has_entries("test3") is True + assert manager.async_has_entries("ignored") is True + assert manager.async_has_entries("disabled") is True + + assert manager.async_has_entries("not") is False assert manager.async_entries(include_ignore=False) == [ entry, entry2a, @@ -712,6 +719,10 @@ async def test_entries_excludes_ignore_and_disabled( entry2b, entry3, ] + assert manager.async_has_entries("test", include_ignore=False) is True + assert manager.async_has_entries("test2", include_ignore=False) is True + assert manager.async_has_entries("test3", include_ignore=False) is True + assert manager.async_has_entries("ignored", include_ignore=False) is False assert manager.async_entries(include_ignore=True) == [ entry, @@ -737,6 +748,10 @@ async def test_entries_excludes_ignore_and_disabled( entry3, disabled_entry, ] + assert manager.async_has_entries("test", include_disabled=False) is True + assert manager.async_has_entries("test2", include_disabled=False) is True + assert manager.async_has_entries("test3", include_disabled=False) is True + assert manager.async_has_entries("disabled", include_disabled=False) is False async def test_saving_and_loading(