Require zeroconf >=0.36 (#118)

This commit is contained in:
Otto Winter 2021-10-13 10:19:42 +02:00 committed by GitHub
parent dec73b8e29
commit dd9d716c10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 4 additions and 79 deletions

View File

@ -1,23 +1,16 @@
import asyncio import asyncio
import contextlib import contextlib
import functools
import socket import socket
from dataclasses import dataclass from dataclasses import dataclass
from ipaddress import IPv4Address, IPv6Address from ipaddress import IPv4Address, IPv6Address
from typing import List, Optional, Tuple, Union, cast from typing import List, Optional, Tuple, Union, cast
import zeroconf import zeroconf
import zeroconf.asyncio
try:
import zeroconf.asyncio
ZC_ASYNCIO = True
except ImportError:
ZC_ASYNCIO = False
from .core import APIConnectionError, ResolveAPIError from .core import APIConnectionError, ResolveAPIError
ZeroconfInstanceType = Union[zeroconf.Zeroconf, "zeroconf.asyncio.AsyncZeroconf", None] ZeroconfInstanceType = Union[zeroconf.Zeroconf, zeroconf.asyncio.AsyncZeroconf, None]
@dataclass(frozen=True) @dataclass(frozen=True)
@ -47,60 +40,12 @@ class AddrInfo:
sockaddr: Sockaddr sockaddr: Sockaddr
def _sync_zeroconf_get_service_info(
zeroconf_instance: ZeroconfInstanceType,
service_type: str,
service_name: str,
timeout: float,
) -> Optional["zeroconf.ServiceInfo"]:
# Use or create zeroconf instance, ensure it's an AsyncZeroconf
if zeroconf_instance is None:
try:
zc = zeroconf.Zeroconf()
except Exception:
raise ResolveAPIError(
"Cannot start mDNS sockets, is this a docker container without "
"host network mode?"
)
do_close = True
elif isinstance(zeroconf_instance, zeroconf.Zeroconf):
zc = zeroconf_instance
do_close = False
else:
raise ValueError(
f"Invalid type passed for zeroconf_instance: {type(zeroconf_instance)}"
)
try:
info = zc.get_service_info(service_type, service_name, int(timeout * 1000))
except Exception as exc:
raise ResolveAPIError(
f"Error resolving mDNS {service_name} via mDNS: {exc}"
) from exc
finally:
if do_close:
zc.close()
return info
async def _async_zeroconf_get_service_info( async def _async_zeroconf_get_service_info(
zeroconf_instance: ZeroconfInstanceType, zeroconf_instance: ZeroconfInstanceType,
service_type: str, service_type: str,
service_name: str, service_name: str,
timeout: float, timeout: float,
) -> Optional["zeroconf.ServiceInfo"]: ) -> Optional["zeroconf.ServiceInfo"]:
if not ZC_ASYNCIO:
return await asyncio.get_event_loop().run_in_executor(
None,
functools.partial(
_sync_zeroconf_get_service_info,
zeroconf_instance,
service_type,
service_name,
timeout,
),
)
# Use or create zeroconf instance, ensure it's an AsyncZeroconf # Use or create zeroconf instance, ensure it's an AsyncZeroconf
if zeroconf_instance is None: if zeroconf_instance is None:
try: try:

View File

@ -58,9 +58,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
# Event for tracking when logic should stop # Event for tracking when logic should stop
self._stop_event = asyncio.Event() self._stop_event = asyncio.Event()
# Store the caller's event loop so the zeroconf can schedule it in the right one
self._event_loop: Optional[asyncio.AbstractEventLoop] = None
@property @property
def _is_stopped(self) -> bool: def _is_stopped(self) -> bool:
return self._stop_event.is_set() return self._stop_event.is_set()
@ -181,7 +178,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
"""Start the reconnecting logic background task.""" """Start the reconnecting logic background task."""
# Create reconnection loop outside of HA's tracked tasks in order # Create reconnection loop outside of HA's tracked tasks in order
# not to delay startup. # not to delay startup.
self._event_loop = asyncio.get_event_loop()
self._loop_task = asyncio.create_task(self._reconnect_loop()) self._loop_task = asyncio.create_task(self._reconnect_loop())
async with self._connected_lock: async with self._connected_lock:
@ -243,7 +239,6 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
) )
self._reconnect_event.set() self._reconnect_event.set()
# From RecordUpdateListener for zeroconf>=0.32
def async_update_records( def async_update_records(
self, self,
zc: "zeroconf.Zeroconf", # pylint: disable=unused-argument zc: "zeroconf.Zeroconf", # pylint: disable=unused-argument
@ -253,18 +248,3 @@ class ReconnectLogic(zeroconf.RecordUpdateListener): # type: ignore[misc,name-d
"""Listen to zeroconf updated mDNS records. This must be called from the eventloop.""" """Listen to zeroconf updated mDNS records. This must be called from the eventloop."""
for update in records: for update in records:
self._async_on_record(update.new) self._async_on_record(update.new)
# From RecordUpdateListener for zeroconf<0.32
def update_record(
self,
zc: "zeroconf.Zeroconf", # pylint: disable=unused-argument
now: float, # pylint: disable=unused-argument
record: "zeroconf.DNSRecord", # type: ignore[name-defined]
) -> None:
assert self._event_loop is not None
async def corofunc() -> None:
self._async_on_record(record)
# Dispatch in event loop
asyncio.run_coroutine_threadsafe(corofunc(), self._event_loop)

View File

@ -1,3 +1,3 @@
protobuf>=3.12.2,<4.0 protobuf>=3.12.2,<4.0
zeroconf>=0.28.0,<1.0 zeroconf>=0.36.0,<1.0
noiseprotocol>=0.3.1,<1.0 noiseprotocol>=0.3.1,<1.0