@@ -201,6 +201,44 @@ def pytest_runtest_setup(item):
201
201
}
202
202
203
203
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
+
204
242
@pytest .yield_fixture
205
243
def event_loop (request ):
206
244
"""Create an instance of the default event loop for each test case."""
@@ -237,3 +275,8 @@ def factory():
237
275
238
276
return port
239
277
return factory
278
+
279
+
280
+ @pytest .fixture
281
+ def advance_time (event_loop ):
282
+ return EventLoopClockAdvancer (event_loop )
0 commit comments