From 5bfd9620db03eef2ae408ebca05dc96a21ec902d Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 12 Oct 2025 10:23:09 -0500 Subject: [PATCH] Handle Wyoming config entries with missing info (#154186) --- .../components/wyoming/config_flow.py | 32 +++++++++---------- tests/components/wyoming/test_config_flow.py | 29 +++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/wyoming/config_flow.py b/homeassistant/components/wyoming/config_flow.py index 41e7b9cf1e6..bbc7676aab4 100644 --- a/homeassistant/components/wyoming/config_flow.py +++ b/homeassistant/components/wyoming/config_flow.py @@ -70,17 +70,13 @@ class WyomingConfigFlow(ConfigFlow, domain=DOMAIN): self._abort_if_unique_id_configured() uri = urlparse(discovery_info.config["uri"]) - for entry in self._async_current_entries(include_ignore=True): - if ( - entry.data[CONF_HOST] == uri.hostname - and entry.data[CONF_PORT] == uri.port - ): - return self.async_update_reload_and_abort( - entry, - unique_id=discovery_info.uuid, - reload_even_if_entry_is_unchanged=False, - reason="already_configured", - ) + for entry in self._iter_entries(uri.hostname, uri.port): + return self.async_update_reload_and_abort( + entry, + unique_id=discovery_info.uuid, + reload_even_if_entry_is_unchanged=False, + reason="already_configured", + ) self._hassio_discovery = discovery_info self.context.update( @@ -139,12 +135,8 @@ class WyomingConfigFlow(ConfigFlow, domain=DOMAIN): self.context["title_placeholders"] = {"name": self._name} - for entry in self._async_current_entries(include_ignore=True): - if ( - entry.data[CONF_HOST] == service.host - and entry.data[CONF_PORT] == service.port - and entry.source != SOURCE_HASSIO - ): + for entry in self._iter_entries(service.host, service.port): + if entry.source != SOURCE_HASSIO: return self.async_update_reload_and_abort( entry, unique_id=unique_id, @@ -176,3 +168,9 @@ class WyomingConfigFlow(ConfigFlow, domain=DOMAIN): CONF_PORT: self._service.port, }, ) + + def _iter_entries(self, host: str, port: int): + """Yield entries with matching host/port.""" + for entry in self._async_current_entries(include_ignore=True): + if entry.data.get(CONF_HOST) == host and entry.data.get(CONF_PORT) == port: + yield entry diff --git a/tests/components/wyoming/test_config_flow.py b/tests/components/wyoming/test_config_flow.py index 30faa2dd441..d9841d9a914 100644 --- a/tests/components/wyoming/test_config_flow.py +++ b/tests/components/wyoming/test_config_flow.py @@ -324,3 +324,32 @@ async def test_zeroconf_discovery_already_configured( assert result.get("type") is FlowResultType.ABORT assert entry.unique_id == "test_zeroconf_name._wyoming._tcp.local._Test Satellite" + + +async def test_bad_config_entry(hass: HomeAssistant) -> None: + """Test we can continue if a config entry is missing info.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={}, # no host/port + ) + entry.add_to_hass(hass) + + # hassio + result = await hass.config_entries.flow.async_init( + DOMAIN, + data=ADDON_DISCOVERY, + context={"source": config_entries.SOURCE_HASSIO}, + ) + assert result.get("type") is FlowResultType.FORM + + # zeroconf + with patch( + "homeassistant.components.wyoming.data.load_wyoming_info", + return_value=SATELLITE_INFO, + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + data=ZEROCONF_DISCOVERY, + context={"source": config_entries.SOURCE_ZEROCONF}, + ) + assert result.get("type") is FlowResultType.FORM