Skip to content

Commit

Permalink
Speed up init and finish flow (#117226)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bdraco committed May 11, 2024
1 parent c979597 commit daef625
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
28 changes: 21 additions & 7 deletions homeassistant/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,8 +1198,8 @@ async def async_init(
# 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,
Expand Down Expand Up @@ -1303,9 +1303,9 @@ async def async_finish_flow(
# 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,
Expand Down Expand Up @@ -1344,10 +1344,9 @@ async def async_finish_flow(
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,
Expand Down Expand Up @@ -1574,6 +1573,21 @@ def async_entry_ids(self) -> list[str]:
"""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,
Expand Down
15 changes: 15 additions & 0 deletions tests/test_config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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(
Expand Down

0 comments on commit daef625

Please sign in to comment.