fix: avoid loading adapter list twice (#1564) · python-zeroconf/python-zeroconf@8359488
@@ -28,7 +28,8 @@
2828import socket
2929import struct
3030import sys
31-from collections.abc import Sequence
31+import warnings
32+from collections.abc import Iterable, Sequence
3233from typing import Any, Union, cast
33343435import ifaddr
@@ -73,19 +74,39 @@ def _encode_address(address: str) -> bytes:
7374return socket.inet_pton(address_family, address)
7475757676-def get_all_addresses() -> list[str]:
77-return list({addr.ip for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv4}) # type: ignore[misc]
77+def get_all_addresses_ipv4(adapters: Iterable[ifaddr.Adapter]) -> list[str]:
78+return list({addr.ip for iface in adapters for addr in iface.ips if addr.is_IPv4}) # type: ignore[misc]
7879798080-def get_all_addresses_v6() -> list[tuple[tuple[str, int, int], int]]:
81+def get_all_addresses_ipv6(adapters: Iterable[ifaddr.Adapter]) -> list[tuple[tuple[str, int, int], int]]:
8182# IPv6 multicast uses positive indexes for interfaces
8283# TODO: What about multi-address interfaces?
8384return list(
84- {(addr.ip, iface.index) for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv6} # type: ignore[misc]
85+ {(addr.ip, iface.index) for iface in adapters for addr in iface.ips if addr.is_IPv6} # type: ignore[misc]
86+ )
87+88+89+def get_all_addresses() -> list[str]:
90+warnings.warn(
91+"get_all_addresses is deprecated, and will be removed in a future version. Use ifaddr"
92+"directly instead to get a list of adapters.",
93+DeprecationWarning,
94+stacklevel=2,
95+ )
96+return get_all_addresses_ipv4(ifaddr.get_adapters())
97+98+99+def get_all_addresses_v6() -> list[tuple[tuple[str, int, int], int]]:
100+warnings.warn(
101+"get_all_addresses_v6 is deprecated, and will be removed in a future version. Use ifaddr"
102+"directly instead to get a list of adapters.",
103+DeprecationWarning,
104+stacklevel=2,
85105 )
106+return get_all_addresses_ipv6(ifaddr.get_adapters())
861078710888-def ip6_to_address_and_index(adapters: list[ifaddr.Adapter], ip: str) -> tuple[tuple[str, int, int], int]:
109+def ip6_to_address_and_index(adapters: Iterable[ifaddr.Adapter], ip: str) -> tuple[tuple[str, int, int], int]:
89110if "%" in ip:
90111ip = ip[: ip.index("%")] # Strip scope_id.
91112ipaddr = ipaddress.ip_address(ip)
@@ -102,7 +123,7 @@ def ip6_to_address_and_index(adapters: list[ifaddr.Adapter], ip: str) -> tuple[t
102123raise RuntimeError(f"No adapter found for IP address {ip}")
103124104125105-def interface_index_to_ip6_address(adapters: list[ifaddr.Adapter], index: int) -> tuple[str, int, int]:
126+def interface_index_to_ip6_address(adapters: Iterable[ifaddr.Adapter], index: int) -> tuple[str, int, int]:
106127for adapter in adapters:
107128if adapter.index == index:
108129for adapter_ip in adapter.ips:
@@ -152,10 +173,11 @@ def normalize_interface_choice(
152173if ip_version != IPVersion.V6Only:
153174result.append("0.0.0.0")
154175elif choice is InterfaceChoice.All:
176+adapters = ifaddr.get_adapters()
155177if ip_version != IPVersion.V4Only:
156-result.extend(get_all_addresses_v6())
178+result.extend(get_all_addresses_ipv6(adapters))
157179if ip_version != IPVersion.V6Only:
158-result.extend(get_all_addresses())
180+result.extend(get_all_addresses_ipv4(adapters))
159181if not result:
160182raise RuntimeError(
161183f"No interfaces to listen on, check that any interfaces have IP version {ip_version}"