File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2626import threading
2727import warnings
2828from abc import abstractmethod
29+ from types import TracebackType # noqa # used in type hints
2930from typing import (
3031 TYPE_CHECKING ,
3132 Callable ,
3536 Optional ,
3637 Set ,
3738 Tuple ,
39+ Type ,
3840 Union ,
3941 cast ,
4042)
@@ -576,3 +578,15 @@ def async_update_records_complete(self) -> None:
576578 for pending in self ._pending_handlers .items ():
577579 self .queue .put (pending )
578580 self ._pending_handlers .clear ()
581+
582+ def __enter__ (self ) -> 'ServiceBrowser' :
583+ return self
584+
585+ def __exit__ ( # pylint: disable=useless-return
586+ self ,
587+ exc_type : Optional [Type [BaseException ]],
588+ exc_val : Optional [BaseException ],
589+ exc_tb : Optional [TracebackType ],
590+ ) -> Optional [bool ]:
591+ self .cancel ()
592+ return None
Original file line number Diff line number Diff line change @@ -93,6 +93,18 @@ def async_update_records_complete(self) -> None:
9393 self ._fire_service_state_changed_event (pending )
9494 self ._pending_handlers .clear ()
9595
96+ async def __aenter__ (self ) -> 'AsyncServiceBrowser' :
97+ return self
98+
99+ async def __aexit__ (
100+ self ,
101+ exc_type : Optional [Type [BaseException ]],
102+ exc_val : Optional [BaseException ],
103+ exc_tb : Optional [TracebackType ],
104+ ) -> Optional [bool ]:
105+ await self .async_cancel ()
106+ return None
107+
96108
97109class AsyncZeroconfServiceTypes (ZeroconfServiceTypes ):
98110 """An async version of ZeroconfServiceTypes."""
Original file line number Diff line number Diff line change 99import time
1010import unittest
1111from threading import Event
12- from typing import Iterable , Set
12+ from typing import Iterable , Set , cast
1313from unittest .mock import patch
1414
1515import pytest
@@ -70,6 +70,31 @@ class MyServiceListener(r.ServiceListener):
7070 zc .close ()
7171
7272
73+ def test_service_browser_cancel_context_manager ():
74+ """Test we can cancel a ServiceBrowser with it being used as a context manager."""
75+
76+ # instantiate a zeroconf instance
77+ zc = Zeroconf (interfaces = ['127.0.0.1' ])
78+ # start a browser
79+ type_ = "_hap._tcp.local."
80+
81+ class MyServiceListener (r .ServiceListener ):
82+ pass
83+
84+ listener = MyServiceListener ()
85+
86+ browser = r .ServiceBrowser (zc , type_ , None , listener )
87+
88+ assert cast (bool , browser .done ) is False
89+
90+ with browser :
91+ pass
92+
93+ assert cast (bool , browser .done ) is True
94+
95+ zc .close ()
96+
97+
7398def test_service_browser_cancel_multiple_times_after_close ():
7499 """Test we can cancel a ServiceBrowser multiple times after close."""
75100
Original file line number Diff line number Diff line change 99import socket
1010import threading
1111import time
12+ from typing import cast
1213from unittest .mock import ANY , call , patch
1314
1415import pytest
@@ -779,6 +780,34 @@ async def test_async_context_manager() -> None:
779780 assert aiosinfo is not None
780781
781782
783+ @pytest .mark .asyncio
784+ async def test_service_browser_cancel_async_context_manager ():
785+ """Test we can cancel an AsyncServiceBrowser with it being used as an async context manager."""
786+
787+ # instantiate a zeroconf instance
788+ aiozc = AsyncZeroconf (interfaces = ['127.0.0.1' ])
789+ zc = aiozc .zeroconf
790+ type_ = "_hap._tcp.local."
791+
792+ class MyServiceListener (ServiceListener ):
793+ pass
794+
795+ listener = MyServiceListener ()
796+
797+ browser = AsyncServiceBrowser (zc , type_ , None , listener )
798+
799+ assert cast (bool , browser .done ) is False
800+
801+ async with browser :
802+ pass
803+
804+ await asyncio .sleep (0 )
805+
806+ assert cast (bool , browser .done ) is True
807+
808+ await aiozc .async_close ()
809+
810+
782811@pytest .mark .asyncio
783812async def test_async_unregister_all_services () -> None :
784813 """Test unregistering all services."""
You can’t perform that action at this time.
0 commit comments