diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 03662ef4ce6..5cf068e2d70 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -20,7 +20,7 @@ from zeroconf import ( IPVersion, ServiceStateChange, ) -from zeroconf.asyncio import AsyncServiceInfo +from zeroconf.asyncio import AsyncServiceBrowser, AsyncServiceInfo from homeassistant import config_entries from homeassistant.components import network @@ -39,7 +39,7 @@ from homeassistant.loader import ( ) from homeassistant.setup import async_when_setup_or_start -from .models import HaAsyncServiceBrowser, HaAsyncZeroconf, HaZeroconf +from .models import HaAsyncZeroconf, HaZeroconf from .usage import install_multiple_zeroconf_catcher _LOGGER = logging.getLogger(__name__) @@ -227,7 +227,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: zeroconf_types, homekit_model_lookup, homekit_model_matchers, - ipv6, ) await discovery.async_setup() @@ -369,7 +368,6 @@ class ZeroconfDiscovery: zeroconf_types: dict[str, list[dict[str, str | dict[str, str]]]], homekit_model_lookups: dict[str, HomeKitDiscoveredIntegration], homekit_model_matchers: dict[re.Pattern, HomeKitDiscoveredIntegration], - ipv6: bool, ) -> None: """Init discovery.""" self.hass = hass @@ -377,10 +375,7 @@ class ZeroconfDiscovery: self.zeroconf_types = zeroconf_types self.homekit_model_lookups = homekit_model_lookups self.homekit_model_matchers = homekit_model_matchers - - self.ipv6 = ipv6 - - self.async_service_browser: HaAsyncServiceBrowser | None = None + self.async_service_browser: AsyncServiceBrowser | None = None async def async_setup(self) -> None: """Start discovery.""" @@ -392,8 +387,8 @@ class ZeroconfDiscovery: if hk_type not in self.zeroconf_types: types.append(hk_type) _LOGGER.debug("Starting Zeroconf browser for: %s", types) - self.async_service_browser = HaAsyncServiceBrowser( - self.ipv6, self.zeroconf, types, handlers=[self.async_service_update] + self.async_service_browser = AsyncServiceBrowser( + self.zeroconf, types, handlers=[self.async_service_update] ) async def async_stop(self) -> None: diff --git a/homeassistant/components/zeroconf/models.py b/homeassistant/components/zeroconf/models.py index ffa5e1a2ecf..7393e699b51 100644 --- a/homeassistant/components/zeroconf/models.py +++ b/homeassistant/components/zeroconf/models.py @@ -1,11 +1,7 @@ """Models for Zeroconf.""" -from typing import Any - -from zeroconf import DNSAddress, DNSRecord, Zeroconf -from zeroconf.asyncio import AsyncServiceBrowser, AsyncZeroconf - -TYPE_AAAA = 28 +from zeroconf import Zeroconf +from zeroconf.asyncio import AsyncZeroconf class HaZeroconf(Zeroconf): @@ -24,22 +20,3 @@ class HaAsyncZeroconf(AsyncZeroconf): """Fake method to avoid integrations closing it.""" ha_async_close = AsyncZeroconf.async_close - - -class HaAsyncServiceBrowser(AsyncServiceBrowser): - """ServiceBrowser that only consumes DNSPointer records.""" - - def __init__(self, ipv6: bool, *args: Any, **kwargs: Any) -> None: - """Create service browser that filters ipv6 if it is disabled.""" - self.ipv6 = ipv6 - super().__init__(*args, **kwargs) - - def update_record(self, zc: Zeroconf, now: float, record: DNSRecord) -> None: - """Pre-Filter AAAA records if IPv6 is not enabled.""" - if ( - not self.ipv6 - and isinstance(record, DNSAddress) - and record.type == TYPE_AAAA - ): - return - super().update_record(zc, now, record) diff --git a/tests/components/zeroconf/test_init.py b/tests/components/zeroconf/test_init.py index 54406bb1b4d..c94b2d66465 100644 --- a/tests/components/zeroconf/test_init.py +++ b/tests/components/zeroconf/test_init.py @@ -34,7 +34,7 @@ HOMEKIT_STATUS_UNPAIRED = b"1" HOMEKIT_STATUS_PAIRED = b"0" -def service_update_mock(ipv6, zeroconf, services, handlers, *, limit_service=None): +def service_update_mock(zeroconf, services, handlers, *, limit_service=None): """Call service update handler.""" for service in services: if limit_service is not None and service != limit_service: @@ -165,7 +165,7 @@ async def test_setup(hass: HomeAssistant, mock_async_zeroconf: None) -> None: ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_service_info_mock, @@ -196,7 +196,7 @@ async def test_setup_with_overly_long_url_and_name( ) -> None: """Test we still setup with long urls and names.""" with patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.get_url", return_value=( @@ -235,7 +235,7 @@ async def test_setup_with_defaults( ) -> None: """Test default interface config.""" with patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_service_info_mock, @@ -254,7 +254,7 @@ async def test_zeroconf_match_macaddress( ) -> None: """Test configured options for a device are loaded via config entry.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -278,7 +278,7 @@ async def test_zeroconf_match_macaddress( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock("FFAADDCC11DD"), @@ -298,7 +298,7 @@ async def test_zeroconf_match_manufacturer( ) -> None: """Test configured options for a device are loaded via config entry.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -318,7 +318,7 @@ async def test_zeroconf_match_manufacturer( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock_manufacturer("Samsung Electronics"), @@ -337,7 +337,7 @@ async def test_zeroconf_match_model( ) -> None: """Test matching a specific model in zeroconf.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -357,7 +357,7 @@ async def test_zeroconf_match_model( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock_model("appletv"), @@ -376,7 +376,7 @@ async def test_zeroconf_match_manufacturer_not_present( ) -> None: """Test matchers reject when a property is missing.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -396,7 +396,7 @@ async def test_zeroconf_match_manufacturer_not_present( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock("aabbccddeeff"), @@ -414,7 +414,7 @@ async def test_zeroconf_no_match( ) -> None: """Test configured options for a device are loaded via config entry.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -430,7 +430,7 @@ async def test_zeroconf_no_match( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock("FFAADDCC11DD"), @@ -448,7 +448,7 @@ async def test_zeroconf_no_match_manufacturer( ) -> None: """Test configured options for a device are loaded via config entry.""" - def http_only_service_update_mock(ipv6, zeroconf, services, handlers): + def http_only_service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -468,7 +468,7 @@ async def test_zeroconf_no_match_manufacturer( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=http_only_service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=http_only_service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock_manufacturer("Not Samsung Electronics"), @@ -497,7 +497,7 @@ async def test_homekit_match_partial_space( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._tcp.local." ), @@ -535,7 +535,7 @@ async def test_device_with_invalid_name( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._tcp.local." ), @@ -568,7 +568,7 @@ async def test_homekit_match_partial_dash( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._udp.local." ), @@ -601,7 +601,7 @@ async def test_homekit_match_partial_fnmatch( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._tcp.local." ), @@ -634,7 +634,7 @@ async def test_homekit_match_full( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._udp.local." ), @@ -670,7 +670,7 @@ async def test_homekit_already_paired( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._tcp.local." ), @@ -704,7 +704,7 @@ async def test_homekit_invalid_paring_status( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._tcp.local." ), @@ -732,7 +732,7 @@ async def test_homekit_not_paired( ), patch.object( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_homekit_info_mock( @@ -770,7 +770,7 @@ async def test_homekit_controller_still_discovered_unpaired_for_cloud( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._udp.local." ), @@ -810,7 +810,7 @@ async def test_homekit_controller_still_discovered_unpaired_for_polling( hass.config_entries.flow, "async_init" ) as mock_config_flow, patch.object( zeroconf, - "HaAsyncServiceBrowser", + "AsyncServiceBrowser", side_effect=lambda *args, **kwargs: service_update_mock( *args, **kwargs, limit_service="_hap._udp.local." ), @@ -940,7 +940,7 @@ async def test_get_instance(hass: HomeAssistant, mock_async_zeroconf: None) -> N async def test_removed_ignored(hass: HomeAssistant, mock_async_zeroconf: None) -> None: """Test we remove it when a zeroconf entry is removed.""" - def service_update_mock(ipv6, zeroconf, services, handlers): + def service_update_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -962,7 +962,7 @@ async def test_removed_ignored(hass: HomeAssistant, mock_async_zeroconf: None) - ) with patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_service_info_mock, @@ -995,7 +995,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route( with patch("homeassistant.components.zeroconf.HaZeroconf") as mock_zc, patch.object( hass.config_entries.flow, "async_init" ), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.network.async_get_adapters", return_value=_ADAPTER_WITH_DEFAULT_ENABLED, @@ -1079,7 +1079,7 @@ async def test_async_detect_interfaces_setting_empty_route_linux( with patch("homeassistant.components.zeroconf.sys.platform", "linux"), patch( "homeassistant.components.zeroconf.HaZeroconf" ) as mock_zc, patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.network.async_get_adapters", return_value=_ADAPTERS_WITH_MANUAL_CONFIG, @@ -1109,7 +1109,7 @@ async def test_async_detect_interfaces_setting_empty_route_freebsd( with patch("homeassistant.components.zeroconf.sys.platform", "freebsd"), patch( "homeassistant.components.zeroconf.HaZeroconf" ) as mock_zc, patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.network.async_get_adapters", return_value=_ADAPTERS_WITH_MANUAL_CONFIG, @@ -1156,7 +1156,7 @@ async def test_async_detect_interfaces_explicitly_set_ipv6_linux( with patch("homeassistant.components.zeroconf.sys.platform", "linux"), patch( "homeassistant.components.zeroconf.HaZeroconf" ) as mock_zc, patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.network.async_get_adapters", return_value=_ADAPTER_WITH_DEFAULT_ENABLED_AND_IPV6, @@ -1181,7 +1181,7 @@ async def test_async_detect_interfaces_explicitly_set_ipv6_freebsd( with patch("homeassistant.components.zeroconf.sys.platform", "freebsd"), patch( "homeassistant.components.zeroconf.HaZeroconf" ) as mock_zc, patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch( "homeassistant.components.zeroconf.network.async_get_adapters", return_value=_ADAPTER_WITH_DEFAULT_ENABLED_AND_IPV6, @@ -1217,7 +1217,7 @@ async def test_setup_with_disallowed_characters_in_local_name( ) -> None: """Test we still setup with disallowed characters in the location name.""" with patch.object(hass.config_entries.flow, "async_init"), patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=service_update_mock + zeroconf, "AsyncServiceBrowser", side_effect=service_update_mock ), patch.object( hass.config, "location_name", @@ -1248,7 +1248,7 @@ async def test_start_with_frontend( async def test_zeroconf_removed(hass: HomeAssistant, mock_async_zeroconf: None) -> None: """Test we dismiss flows when a PTR record is removed.""" - def _device_removed_mock(ipv6, zeroconf, services, handlers): + def _device_removed_mock(zeroconf, services, handlers): """Call service update handler.""" handlers[0]( zeroconf, @@ -1275,7 +1275,7 @@ async def test_zeroconf_removed(hass: HomeAssistant, mock_async_zeroconf: None) ) as mock_async_progress_by_init_data_type, patch.object( hass.config_entries.flow, "async_abort" ) as mock_async_abort, patch.object( - zeroconf, "HaAsyncServiceBrowser", side_effect=_device_removed_mock + zeroconf, "AsyncServiceBrowser", side_effect=_device_removed_mock ) as mock_service_browser, patch( "homeassistant.components.zeroconf.AsyncServiceInfo", side_effect=get_zeroconf_info_mock("FFAADDCC11DD"), diff --git a/tests/conftest.py b/tests/conftest.py index 1948b001ad4..696a5a2ed15 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1131,7 +1131,7 @@ def mock_zeroconf() -> Generator[None, None, None]: with patch( "homeassistant.components.zeroconf.HaZeroconf", autospec=True ) as mock_zc, patch( - "homeassistant.components.zeroconf.HaAsyncServiceBrowser", autospec=True + "homeassistant.components.zeroconf.AsyncServiceBrowser", autospec=True ): zc = mock_zc.return_value # DNSCache has strong Cython type checks, and MagicMock does not work