fix: avoid loading adapter list twice (#1564) · python-zeroconf/python-zeroconf@8359488

@@ -28,7 +28,8 @@

2828

import socket

2929

import struct

3030

import sys

31-

from collections.abc import Sequence

31+

import warnings

32+

from collections.abc import Iterable, Sequence

3233

from typing import Any, Union, cast

33343435

import ifaddr

@@ -73,19 +74,39 @@ def _encode_address(address: str) -> bytes:

7374

return 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?

8384

return 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]:

89110

if "%" in ip:

90111

ip = ip[: ip.index("%")] # Strip scope_id.

91112

ipaddr = ipaddress.ip_address(ip)

@@ -102,7 +123,7 @@ def ip6_to_address_and_index(adapters: list[ifaddr.Adapter], ip: str) -> tuple[t

102123

raise 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]:

106127

for adapter in adapters:

107128

if adapter.index == index:

108129

for adapter_ip in adapter.ips:

@@ -152,10 +173,11 @@ def normalize_interface_choice(

152173

if ip_version != IPVersion.V6Only:

153174

result.append("0.0.0.0")

154175

elif choice is InterfaceChoice.All:

176+

adapters = ifaddr.get_adapters()

155177

if ip_version != IPVersion.V4Only:

156-

result.extend(get_all_addresses_v6())

178+

result.extend(get_all_addresses_ipv6(adapters))

157179

if ip_version != IPVersion.V6Only:

158-

result.extend(get_all_addresses())

180+

result.extend(get_all_addresses_ipv4(adapters))

159181

if not result:

160182

raise RuntimeError(

161183

f"No interfaces to listen on, check that any interfaces have IP version {ip_version}"