Do not mutate generated zeroconf matchers in async_get_zeroconf (#183330)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Franck Nijhof
2026-09-30 12:52:15 +01:00
committed by GitHub
co-authored by Claude
parent 433be108e9
commit d49635647a
2 changed files with 33 additions and 1 deletions
+6 -1
View File
@@ -516,7 +516,12 @@ async def async_get_zeroconf(
hass: HomeAssistant,
) -> dict[str, list[ZeroconfMatcher]]:
"""Return cached list of zeroconf types."""
zeroconf: dict[str, list[ZeroconfMatcher]] = ZEROCONF.copy() # type: ignore[assignment]
# Copy the lists too, custom integrations append to them below
generated_zeroconf = cast(dict[str, list[ZeroconfMatcher]], ZEROCONF)
zeroconf = {
service_type: list(matchers)
for service_type, matchers in generated_zeroconf.items()
}
integrations = await async_get_custom_components(hass)
for integration in integrations.values():
+27
View File
@@ -15,6 +15,7 @@ from homeassistant import loader
from homeassistant.components import hue
from homeassistant.components.hue import light as hue_light
from homeassistant.core import HomeAssistant
from homeassistant.generated.zeroconf import ZEROCONF
from homeassistant.helpers.json import json_dumps
from homeassistant.util.json import json_loads
@@ -895,6 +896,32 @@ async def test_get_zeroconf(hass: HomeAssistant) -> None:
]
async def test_get_zeroconf_does_not_mutate_generated(hass: HomeAssistant) -> None:
"""Verify custom matchers for an existing type do not leak into the generated table."""
integration = loader.Integration(
hass,
"custom_components.test_http",
None,
{
"name": "test_http",
"domain": "test_http",
"config_flow": True,
"dependencies": [],
"requirements": [],
"zeroconf": ["_http._tcp.local."],
},
)
generated = list(ZEROCONF["_http._tcp.local."])
with patch("homeassistant.loader.async_get_custom_components") as mock_get:
mock_get.return_value = {"test_http": integration}
await loader.async_get_zeroconf(hass)
zeroconf = await loader.async_get_zeroconf(hass)
assert zeroconf["_http._tcp.local."] == [*generated, {"domain": "test_http"}]
assert ZEROCONF["_http._tcp.local."] == generated
async def test_get_application_credentials(hass: HomeAssistant) -> None:
"""Verify that custom components with application_credentials are found."""
test_1_integration = _get_test_integration(hass, "test_1", True)