Skip to content

Commit df969ff

Browse files
committed
Add an AsyncZeroconfServiceTypes to mirror ZeroconfServiceTypes to zeroconf.aio
1 parent 5752ace commit df969ff

2 files changed

Lines changed: 86 additions & 3 deletions

File tree

tests/test_aio.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import pytest
1313

14-
from zeroconf.aio import AsyncServiceInfo, AsyncServiceListener, AsyncZeroconf
14+
from zeroconf.aio import AsyncServiceInfo, AsyncServiceListener, AsyncZeroconf, AsyncZeroconfServiceTypes
1515
from zeroconf import Zeroconf
1616
from zeroconf.const import _LISTENER_TIME
1717
from zeroconf._exceptions import BadTypeInNameException, NonUniqueNameException, ServiceNameAlreadyRegistered
@@ -558,3 +558,37 @@ async def test_async_unregister_all_services() -> None:
558558
await aiozc.async_unregister_all_services()
559559

560560
await aiozc.async_close()
561+
562+
563+
@pytest.mark.asyncio
564+
async def test_async_zeroconf_service_types():
565+
type_ = "_test-srvc-type._tcp.local."
566+
name = "xxxyyy"
567+
registration_name = "%s.%s" % (name, type_)
568+
569+
zeroconf_registrar = AsyncZeroconf(interfaces=['127.0.0.1'])
570+
desc = {'path': '/~paulsm/'}
571+
info = ServiceInfo(
572+
type_,
573+
registration_name,
574+
80,
575+
0,
576+
0,
577+
desc,
578+
"ash-2.local.",
579+
addresses=[socket.inet_aton("10.0.1.2")],
580+
)
581+
task = await zeroconf_registrar.async_register_service(info)
582+
await task
583+
# Ensure we do not clear the cache until after the last broadcast is processed
584+
await asyncio.sleep(0.2)
585+
_clear_cache(zeroconf_registrar.zeroconf)
586+
try:
587+
service_types = await AsyncZeroconfServiceTypes.async_find(interfaces=['127.0.0.1'], timeout=0.5)
588+
assert type_ in service_types
589+
_clear_cache(zeroconf_registrar.zeroconf)
590+
service_types = await AsyncZeroconfServiceTypes.async_find(aiozc=zeroconf_registrar, timeout=0.5)
591+
assert type_ in service_types
592+
593+
finally:
594+
await zeroconf_registrar.async_close()

zeroconf/aio.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,32 @@
2222
import asyncio
2323
import contextlib
2424
from types import TracebackType # noqa # used in type hints
25-
from typing import Awaitable, Callable, Dict, List, Optional, Type, Union
25+
from typing import Awaitable, Callable, Dict, List, Optional, Tuple, Type, Union
2626

2727
from ._core import NotifyListener, Zeroconf
2828
from ._exceptions import NonUniqueNameException
2929
from ._services import ServiceInfo, _ServiceBrowserBase, instance_name_from_service_info
30+
from ._services.types import ZeroconfServiceTypes
3031
from ._utils.aio import wait_condition_or_timeout
3132
from ._utils.net import IPVersion, InterfaceChoice, InterfacesType
3233
from ._utils.time import current_time_millis, millis_to_seconds
33-
from .const import _BROWSER_TIME, _CHECK_TIME, _LISTENER_TIME, _MDNS_PORT, _REGISTER_TIME, _UNREGISTER_TIME
34+
from .const import (
35+
_BROWSER_TIME,
36+
_CHECK_TIME,
37+
_LISTENER_TIME,
38+
_MDNS_PORT,
39+
_REGISTER_TIME,
40+
_SERVICE_TYPE_ENUMERATION_NAME,
41+
_UNREGISTER_TIME,
42+
)
3443

3544

3645
__all__ = [
3746
"AsyncZeroconf",
3847
"AsyncServiceInfo",
3948
"AsyncServiceBrowser",
4049
"AsyncServiceListener",
50+
"AsyncZeroconfServiceTypes",
4151
]
4252

4353

@@ -164,6 +174,45 @@ async def async_run(self) -> None:
164174
)
165175

166176

177+
class AsyncZeroconfServiceTypes(ZeroconfServiceTypes):
178+
"""An async version of ZeroconfServiceTypes."""
179+
180+
@classmethod
181+
async def async_find(
182+
cls,
183+
aiozc: Optional['AsyncZeroconf'] = None,
184+
timeout: Union[int, float] = 5,
185+
interfaces: InterfacesType = InterfaceChoice.All,
186+
ip_version: Optional[IPVersion] = None,
187+
) -> Tuple[str, ...]:
188+
"""
189+
Return all of the advertised services on any local networks.
190+
191+
:param aiozc: AsyncZeroconf() instance. Pass in if already have an
192+
instance running or if non-default interfaces are needed
193+
:param timeout: seconds to wait for any responses
194+
:param interfaces: interfaces to listen on.
195+
:param ip_version: IP protocol version to use.
196+
:return: tuple of service type strings
197+
"""
198+
local_zc = aiozc or AsyncZeroconf(interfaces=interfaces, ip_version=ip_version)
199+
listener = cls()
200+
async_browser = AsyncServiceBrowser(
201+
local_zc, _SERVICE_TYPE_ENUMERATION_NAME, listener=listener # type: ignore
202+
)
203+
204+
# wait for responses
205+
await asyncio.sleep(timeout)
206+
207+
await async_browser.async_cancel()
208+
209+
# close down anything we opened
210+
if aiozc is None:
211+
await local_zc.async_close()
212+
213+
return tuple(sorted(listener.found_services))
214+
215+
167216
class AsyncZeroconf:
168217
"""Implementation of Zeroconf Multicast DNS Service Discovery
169218

0 commit comments

Comments
 (0)