@@ -201,6 +201,44 @@ def pytest_runtest_setup(item):
201201}
202202
203203
204+ class EventLoopClockAdvancer :
205+ """
206+ A helper object that when called will advance the event loop's time. If the
207+ call is awaited, the caller task will wait an iteration for the update to
208+ wake up any awaiting handlers.
209+ """
210+ __slots__ = ("offset" , "loop" , "_base_time" ,)
211+
212+ def __init__ (self , loop ):
213+ self .offset = 0.0
214+ self ._base_time = loop .time
215+ self .loop = loop
216+
217+ # incorporate offset timing into the event loop
218+ self .loop .time = self .time
219+
220+ def time (self ):
221+ """
222+ Return the time according to the event loop's clock. The time is
223+ adjusted by an offset.
224+ """
225+ return self ._base_time () + self .offset
226+
227+ def __call__ (self , seconds ):
228+ """
229+ Advance time by a given offset in seconds. Returns an awaitable
230+ that will complete after all tasks scheduled for after advancement
231+ of time are proceeding.
232+ """
233+ if seconds > 0 :
234+ # advance the clock by the given offset
235+ self .offset += abs (seconds )
236+
237+ # Once the clock is adjusted, new tasks may have just been
238+ # scheduled for running in the next pass through the event loop
239+ return self .loop .create_task (asyncio .sleep (0 ))
240+
241+
204242@pytest .yield_fixture
205243def event_loop (request ):
206244 """Create an instance of the default event loop for each test case."""
@@ -237,3 +275,8 @@ def factory():
237275
238276 return port
239277 return factory
278+
279+
280+ @pytest .fixture
281+ def advance_time (event_loop ):
282+ return EventLoopClockAdvancer (event_loop )
0 commit comments