|
8 | 8 | import socket |
9 | 9 | import subprocess |
10 | 10 | from subprocess import PIPE, Popen |
11 | | -from typing import Any, Callable, Iterable, Sequence |
| 11 | +from typing import Any, Callable, Iterable, Mapping, Sequence |
12 | 12 | from warnings import warn |
13 | 13 |
|
14 | | -LOCAL_IPS: list = [] |
15 | | -PUBLIC_IPS: list = [] |
| 14 | +LOCAL_IPS: list[str] = [] |
| 15 | +PUBLIC_IPS: list[str] = [] |
16 | 16 |
|
17 | 17 | LOCALHOST: str = "" |
18 | 18 |
|
@@ -75,27 +75,34 @@ class NoIPAddresses(Exception): # noqa |
75 | 75 | pass |
76 | 76 |
|
77 | 77 |
|
78 | | -def _populate_from_list(addrs: Sequence[str] | None) -> None: |
| 78 | +def _populate_from_list(addrs: Sequence[str]) -> None: |
79 | 79 | """populate local and public IPs from flat list of all IPs""" |
| 80 | + _populate_from_dict({"all": addrs}) |
| 81 | + |
| 82 | + |
| 83 | +def _populate_from_dict(addrs: Mapping[str, Sequence[str]]) -> None: |
| 84 | + """populate local and public IPs from dict of {'en0': 'ip'}""" |
80 | 85 | if not addrs: |
81 | | - raise NoIPAddresses |
| 86 | + raise NoIPAddresses() |
82 | 87 |
|
83 | 88 | global LOCALHOST |
84 | 89 | public_ips = [] |
85 | 90 | local_ips = [] |
86 | 91 |
|
87 | | - for ip in addrs: |
88 | | - local_ips.append(ip) |
89 | | - if not ip.startswith("127."): |
90 | | - public_ips.append(ip) |
91 | | - elif not LOCALHOST: |
92 | | - LOCALHOST = ip |
| 92 | + for iface, ip_list in addrs.items(): |
| 93 | + for ip in ip_list: |
| 94 | + local_ips.append(ip) |
| 95 | + if not LOCALHOST and (iface.startswith("lo") or ip.startswith("127.")): |
| 96 | + LOCALHOST = ip |
| 97 | + if not iface.startswith("lo") and not ip.startswith(("127.", "169.254.")): |
| 98 | + # don't include link-local address in public_ips |
| 99 | + public_ips.append(ip) |
93 | 100 |
|
94 | 101 | if not LOCALHOST or LOCALHOST == "127.0.0.1": |
95 | 102 | LOCALHOST = "127.0.0.1" |
96 | 103 | local_ips.insert(0, LOCALHOST) |
97 | 104 |
|
98 | | - local_ips.extend(["0.0.0.0", ""]) # noqa |
| 105 | + local_ips.extend(["0.0.0.0", ""]) # noqa: S104 |
99 | 106 |
|
100 | 107 | LOCAL_IPS[:] = _uniq_stable(local_ips) |
101 | 108 | PUBLIC_IPS[:] = _uniq_stable(public_ips) |
@@ -155,59 +162,38 @@ def _load_ips_psutil() -> None: |
155 | 162 | """load ip addresses with netifaces""" |
156 | 163 | import psutil |
157 | 164 |
|
158 | | - global LOCALHOST |
159 | | - local_ips = [] |
160 | | - public_ips = [] |
| 165 | + addr_dict: dict[str, list[str]] = {} |
161 | 166 |
|
162 | 167 | # dict of iface_name: address_list, eg |
163 | 168 | # {"lo": [snicaddr(family=<AddressFamily.AF_INET>, address="127.0.0.1", |
164 | 169 | # ...), snicaddr(family=<AddressFamily.AF_INET6>, ...)]} |
165 | 170 | for iface, ifaddresses in psutil.net_if_addrs().items(): |
166 | | - for address_data in ifaddresses: |
167 | | - if address_data.family == socket.AF_INET: |
168 | | - addr = address_data.address |
169 | | - if not (iface.startswith("lo") or addr.startswith("127.")): |
170 | | - public_ips.append(addr) |
171 | | - elif not LOCALHOST: |
172 | | - LOCALHOST = addr |
173 | | - local_ips.append(addr) |
174 | | - if not LOCALHOST: |
175 | | - # we never found a loopback interface (can this ever happen?), assume common default |
176 | | - LOCALHOST = "127.0.0.1" |
177 | | - local_ips.insert(0, LOCALHOST) |
178 | | - local_ips.extend(["0.0.0.0", ""]) # noqa |
179 | | - LOCAL_IPS[:] = _uniq_stable(local_ips) |
180 | | - PUBLIC_IPS[:] = _uniq_stable(public_ips) |
| 171 | + addr_dict[iface] = [ |
| 172 | + address_data.address |
| 173 | + for address_data in ifaddresses |
| 174 | + if address_data.family == socket.AF_INET |
| 175 | + ] |
| 176 | + |
| 177 | + _populate_from_dict(addr_dict) |
181 | 178 |
|
182 | 179 |
|
183 | 180 | def _load_ips_netifaces() -> None: |
184 | 181 | """load ip addresses with netifaces""" |
185 | 182 | import netifaces # type: ignore[import-not-found] |
186 | 183 |
|
187 | | - global LOCALHOST |
188 | | - local_ips = [] |
189 | | - public_ips = [] |
| 184 | + addr_dict: dict[str, list[str]] = {} |
190 | 185 |
|
191 | 186 | # list of iface names, 'lo0', 'eth0', etc. |
192 | 187 | for iface in netifaces.interfaces(): |
193 | 188 | # list of ipv4 addrinfo dicts |
| 189 | + addr_dict[iface] = [] |
| 190 | + |
194 | 191 | ipv4s = netifaces.ifaddresses(iface).get(netifaces.AF_INET, []) |
195 | 192 | for entry in ipv4s: |
196 | 193 | addr = entry.get("addr") |
197 | | - if not addr: |
198 | | - continue |
199 | | - if not (iface.startswith("lo") or addr.startswith("127.")): |
200 | | - public_ips.append(addr) |
201 | | - elif not LOCALHOST: |
202 | | - LOCALHOST = addr |
203 | | - local_ips.append(addr) |
204 | | - if not LOCALHOST: |
205 | | - # we never found a loopback interface (can this ever happen?), assume common default |
206 | | - LOCALHOST = "127.0.0.1" |
207 | | - local_ips.insert(0, LOCALHOST) |
208 | | - local_ips.extend(["0.0.0.0", ""]) # noqa |
209 | | - LOCAL_IPS[:] = _uniq_stable(local_ips) |
210 | | - PUBLIC_IPS[:] = _uniq_stable(public_ips) |
| 194 | + if addr: |
| 195 | + addr_dict[iface].append(addr) |
| 196 | + _populate_from_dict(addr_dict) |
211 | 197 |
|
212 | 198 |
|
213 | 199 | def _load_ips_gethostbyname() -> None: |
|
0 commit comments