Skip to content

Commit 8d8e0f4

Browse files
authored
Migrate to using zeroconf built-in address resolver classes (#19)
1 parent 7bce435 commit 8d8e0f4

File tree

4 files changed

+49
-40
lines changed

4 files changed

+49
-40
lines changed

CHANGES/19.misc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Migrated to using zeroconf's built-in resolver classes -- by :user:`bdraco`.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "aiohttp-asyncmdnsresolver"
7-
dependencies = ["aiodns>=3.2.0", "aiohttp>=3.10.0", "zeroconf>=0.132.0"]
7+
dependencies = ["aiodns>=3.2.0", "aiohttp>=3.10.0", "zeroconf>=0.142.0"]
88
description = "An async resolver for aiohttp that supports MDNS"
99
dynamic = ["version"]
1010
license = {file = "LICENSE"}

src/aiohttp_asyncmdnsresolver/_impl.py

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,25 @@
44

55
import socket
66
from typing import Any
7-
from zeroconf import IPVersion
8-
from zeroconf.asyncio import AsyncZeroconf, AsyncServiceInfo
7+
from zeroconf.asyncio import AsyncZeroconf
8+
from zeroconf import (
9+
AddressResolver,
10+
AddressResolverIPv4,
11+
AddressResolverIPv6,
12+
IPVersion,
13+
)
914
from aiohttp.resolver import AsyncResolver, ResolveResult
1015
from ipaddress import IPv4Address, IPv6Address
1116

12-
13-
class IPv6orIPv4HostResolver(AsyncServiceInfo):
14-
"""Resolve a host name to an IP address."""
15-
16-
@property
17-
def _is_complete(self) -> bool:
18-
"""The ServiceInfo has all expected properties."""
19-
return bool(self._ipv4_addresses) or bool(self._ipv6_addresses)
20-
21-
22-
class IPv6HostResolver(AsyncServiceInfo):
23-
"""Resolve a host name to an IP address."""
24-
25-
@property
26-
def _is_complete(self) -> bool:
27-
"""The ServiceInfo has all expected properties."""
28-
return bool(self._ipv6_addresses)
29-
30-
31-
class IPv4HostResolver(AsyncServiceInfo):
32-
"""Resolve a host name to an IP address."""
33-
34-
@property
35-
def _is_complete(self) -> bool:
36-
"""The ServiceInfo has all expected properties."""
37-
return bool(self._ipv4_addresses)
38-
39-
4017
DEFAULT_TIMEOUT = 5.0
4118

42-
_FAMILY_TO_RESOLVER_CLASS = {
43-
socket.AF_INET: IPv4HostResolver,
44-
socket.AF_INET6: IPv6HostResolver,
45-
socket.AF_UNSPEC: IPv6orIPv4HostResolver,
19+
_FAMILY_TO_RESOLVER_CLASS: dict[
20+
socket.AddressFamily,
21+
type[AddressResolver] | type[AddressResolverIPv4] | type[AddressResolverIPv6],
22+
] = {
23+
socket.AF_INET: AddressResolverIPv4,
24+
socket.AF_INET6: AddressResolverIPv6,
25+
socket.AF_UNSPEC: AddressResolver,
4626
}
4727
_FAMILY_TO_IP_VERSION = {
4828
socket.AF_INET: IPVersion.V4Only,
@@ -98,11 +78,11 @@ async def _resolve_mdns(
9878
self, host: str, port: int, family: socket.AddressFamily
9979
) -> list[ResolveResult]:
10080
"""Resolve a host name to an IP address using mDNS."""
101-
resolver_class: type[AsyncServiceInfo] = _FAMILY_TO_RESOLVER_CLASS[family]
81+
resolver_class = _FAMILY_TO_RESOLVER_CLASS[family]
10282
ip_version: IPVersion = _FAMILY_TO_IP_VERSION[family]
10383
if host[-1] != ".":
10484
host += "."
105-
info = resolver_class(".local.", host, server=host)
85+
info = resolver_class(host)
10686
if (
10787
info.load_from_cache(self._aiozc.zeroconf)
10888
or (

tests/test_impl.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,41 @@
77
from unittest.mock import patch
88
from ipaddress import IPv6Address, IPv4Address
99
import socket
10+
from collections.abc import Generator
1011
from aiohttp_asyncmdnsresolver._impl import (
11-
IPv4HostResolver,
12-
IPv6HostResolver,
13-
IPv6orIPv4HostResolver,
12+
_FAMILY_TO_RESOLVER_CLASS,
13+
AddressResolver,
14+
AddressResolverIPv4,
15+
AddressResolverIPv6,
1416
)
1517

1618

19+
class IPv6orIPv4HostResolver(AddressResolver):
20+
"""Patchable class for testing."""
21+
22+
23+
class IPv4HostResolver(AddressResolverIPv4):
24+
"""Patchable class for testing."""
25+
26+
27+
class IPv6HostResolver(AddressResolverIPv6):
28+
"""Patchable class for testing."""
29+
30+
31+
@pytest.fixture(autouse=True)
32+
def make_resolvers_patchable() -> Generator[None, None, None]:
33+
"""Patch the resolvers."""
34+
with patch.dict(
35+
_FAMILY_TO_RESOLVER_CLASS,
36+
{
37+
socket.AF_INET: IPv4HostResolver,
38+
socket.AF_INET6: IPv6HostResolver,
39+
socket.AF_UNSPEC: IPv6orIPv4HostResolver,
40+
},
41+
):
42+
yield
43+
44+
1745
@pytest_asyncio.fixture
1846
async def resolver() -> AsyncGenerator[AsyncMDNSResolver]:
1947
"""Return a resolver."""

0 commit comments

Comments
 (0)