@@ -1762,3 +1762,77 @@ def async_update_records(self, zc: 'Zeroconf', now: float, records: List[r.Recor
17621762 )
17631763
17641764 await aiozc .async_close ()
1765+
1766+
1767+ @pytest .mark .asyncio
1768+ async def test_async_updates_iteration_safe ():
1769+ """Ensure we can safely iterate over the async_updates."""
1770+
1771+ aiozc = AsyncZeroconf (interfaces = ['127.0.0.1' ])
1772+ zc : Zeroconf = aiozc .zeroconf
1773+ updated = []
1774+ good_bye_answer = r .DNSPointer (
1775+ "myservicelow_tcp._tcp.local." ,
1776+ const ._TYPE_PTR ,
1777+ const ._CLASS_IN | const ._CLASS_UNIQUE ,
1778+ 0 ,
1779+ 'goodbye.local.' ,
1780+ )
1781+
1782+ class OtherListener (r .RecordUpdateListener ):
1783+ """A RecordUpdateListener that does not implement update_records."""
1784+
1785+ def async_update_records (self , zc : 'Zeroconf' , now : float , records : List [r .RecordUpdate ]) -> None :
1786+ """Update multiple records in one shot."""
1787+ updated .extend (records )
1788+
1789+ other = OtherListener ()
1790+
1791+ class ListenerThatAddsListener (r .RecordUpdateListener ):
1792+ """A RecordUpdateListener that does not implement update_records."""
1793+
1794+ def async_update_records (self , zc : 'Zeroconf' , now : float , records : List [r .RecordUpdate ]) -> None :
1795+ """Update multiple records in one shot."""
1796+ updated .extend (records )
1797+ zc .async_add_listener (other , None )
1798+
1799+ zc .async_add_listener (ListenerThatAddsListener (), None )
1800+ await asyncio .sleep (0 ) # flush out any call soons
1801+
1802+ # This should not raise RuntimeError: set changed size during iteration
1803+ zc .record_manager .async_updates (
1804+ now = current_time_millis (), records = [r .RecordUpdate (good_bye_answer , None )]
1805+ )
1806+
1807+ assert len (updated ) == 1
1808+ await aiozc .async_close ()
1809+
1810+
1811+ @pytest .mark .asyncio
1812+ async def test_async_updates_complete_iteration_safe ():
1813+ """Ensure we can safely iterate over the async_updates_complete."""
1814+
1815+ aiozc = AsyncZeroconf (interfaces = ['127.0.0.1' ])
1816+ zc : Zeroconf = aiozc .zeroconf
1817+
1818+ class OtherListener (r .RecordUpdateListener ):
1819+ """A RecordUpdateListener that does not implement update_records."""
1820+
1821+ def async_update_records_complete (self ) -> None :
1822+ """Update multiple records in one shot."""
1823+
1824+ other = OtherListener ()
1825+
1826+ class ListenerThatAddsListener (r .RecordUpdateListener ):
1827+ """A RecordUpdateListener that does not implement update_records."""
1828+
1829+ def async_update_records_complete (self ) -> None :
1830+ """Update multiple records in one shot."""
1831+ zc .async_add_listener (other , None )
1832+
1833+ zc .async_add_listener (ListenerThatAddsListener (), None )
1834+ await asyncio .sleep (0 ) # flush out any call soons
1835+
1836+ # This should not raise RuntimeError: set changed size during iteration
1837+ zc .record_manager .async_updates_complete (False )
1838+ await aiozc .async_close ()
0 commit comments