Skip to content

Commit c4c2dee

Browse files
authored
feat: make async_get_service_info available on the Zeroconf object (#1366)
1 parent 0108b50 commit c4c2dee

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

src/zeroconf/_core.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@
3939
from ._protocol.outgoing import DNSOutgoing
4040
from ._services import ServiceListener
4141
from ._services.browser import ServiceBrowser
42-
from ._services.info import ServiceInfo, instance_name_from_service_info
42+
from ._services.info import (
43+
AsyncServiceInfo,
44+
ServiceInfo,
45+
instance_name_from_service_info,
46+
)
4347
from ._services.registry import ServiceRegistry
4448
from ._transport import _WrappedTransport
4549
from ._updates import RecordUpdateListener
@@ -261,7 +265,13 @@ def get_service_info(
261265
) -> Optional[ServiceInfo]:
262266
"""Returns network's service information for a particular
263267
name and type, or None if no service matches by the timeout,
264-
which defaults to 3 seconds."""
268+
which defaults to 3 seconds.
269+
270+
:param type_: fully qualified service type name
271+
:param name: the name of the service
272+
:param timeout: milliseconds to wait for a response
273+
:param question_type: The type of questions to ask (DNSQuestionType.QM or DNSQuestionType.QU)
274+
"""
265275
info = ServiceInfo(type_, name)
266276
if info.request(self, timeout, question_type):
267277
return info
@@ -360,6 +370,23 @@ async def async_update_service(self, info: ServiceInfo) -> Awaitable:
360370
self.registry.async_update(info)
361371
return asyncio.ensure_future(self._async_broadcast_service(info, _REGISTER_TIME, None))
362372

373+
async def async_get_service_info(
374+
self, type_: str, name: str, timeout: int = 3000, question_type: Optional[DNSQuestionType] = None
375+
) -> Optional[AsyncServiceInfo]:
376+
"""Returns network's service information for a particular
377+
name and type, or None if no service matches by the timeout,
378+
which defaults to 3 seconds.
379+
380+
:param type_: fully qualified service type name
381+
:param name: the name of the service
382+
:param timeout: milliseconds to wait for a response
383+
:param question_type: The type of questions to ask (DNSQuestionType.QM or DNSQuestionType.QU)
384+
"""
385+
info = AsyncServiceInfo(type_, name)
386+
if await info.async_request(self, timeout, question_type):
387+
return info
388+
return None
389+
363390
async def _async_broadcast_service(
364391
self,
365392
info: ServiceInfo,

src/zeroconf/_services/info.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,12 @@ def request(
770770
While it is not expected during normal operation,
771771
this function may raise EventLoopBlocked if the underlying
772772
call to `async_request` cannot be completed.
773+
774+
:param zc: Zeroconf instance
775+
:param timeout: time in milliseconds to wait for a response
776+
:param question_type: question type to ask
777+
:param addr: address to send the request to
778+
:param port: port to send the request to
773779
"""
774780
assert zc.loop is not None and zc.loop.is_running()
775781
if zc.loop == get_running_loop():
@@ -803,6 +809,12 @@ async def async_request(
803809
mDNS multicast address and port. This is useful for directing
804810
requests to a specific host that may be able to respond across
805811
subnets.
812+
813+
:param zc: Zeroconf instance
814+
:param timeout: time in milliseconds to wait for a response
815+
:param question_type: question type to ask
816+
:param addr: address to send the request to
817+
:param port: port to send the request to
806818
"""
807819
if not zc.started:
808820
await zc.async_wait_for_start()
@@ -924,3 +936,7 @@ def __repr__(self) -> str:
924936
)
925937
),
926938
)
939+
940+
941+
class AsyncServiceInfo(ServiceInfo):
942+
"""An async version of ServiceInfo."""

src/zeroconf/asyncio.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from ._dns import DNSQuestionType
2929
from ._services import ServiceListener
3030
from ._services.browser import _ServiceBrowserBase
31-
from ._services.info import ServiceInfo
31+
from ._services.info import AsyncServiceInfo, ServiceInfo
3232
from ._services.types import ZeroconfServiceTypes
3333
from ._utils.net import InterfaceChoice, InterfacesType, IPVersion
3434
from .const import _BROWSER_TIME, _MDNS_PORT, _SERVICE_TYPE_ENUMERATION_NAME
@@ -41,10 +41,6 @@
4141
]
4242

4343

44-
class AsyncServiceInfo(ServiceInfo):
45-
"""An async version of ServiceInfo."""
46-
47-
4844
class AsyncServiceBrowser(_ServiceBrowserBase):
4945
"""Used to browse for a service for specific type(s).
5046
@@ -239,11 +235,14 @@ async def async_get_service_info(
239235
) -> Optional[AsyncServiceInfo]:
240236
"""Returns network's service information for a particular
241237
name and type, or None if no service matches by the timeout,
242-
which defaults to 3 seconds."""
243-
info = AsyncServiceInfo(type_, name)
244-
if await info.async_request(self.zeroconf, timeout, question_type):
245-
return info
246-
return None
238+
which defaults to 3 seconds.
239+
240+
:param type_: fully qualified service type name
241+
:param name: the name of the service
242+
:param timeout: milliseconds to wait for a response
243+
:param question_type: The type of questions to ask (DNSQuestionType.QM or DNSQuestionType.QU)
244+
"""
245+
return await self.zeroconf.async_get_service_info(type_, name, timeout, question_type)
247246

248247
async def async_add_service_listener(self, type_: str, listener: ServiceListener) -> None:
249248
"""Adds a listener for a particular service type. This object

tests/test_asyncio.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,10 @@ async def test_service_info_async_request() -> None:
680680
assert aiosinfo is not None
681681
assert aiosinfo.addresses == [socket.inet_aton("10.0.1.3")]
682682

683+
aiosinfo = await aiozc.zeroconf.async_get_service_info(type_, registration_name)
684+
assert aiosinfo is not None
685+
assert aiosinfo.addresses == [socket.inet_aton("10.0.1.3")]
686+
683687
aiosinfos = await asyncio.gather(
684688
aiozc.async_get_service_info(type_, registration_name),
685689
aiozc.async_get_service_info(type_, registration_name2),

0 commit comments

Comments
 (0)