looptime

raw JSON →
0.7 verified Mon Apr 27 auth: no python

Utility to fast-forward asyncio event loop time for deterministic testing. Current version 0.7, requires Python >=3.10. Released as a standalone package to replace pytest-asyncio's `loop_context` for controlling virtual time.

pip install looptime
error AttributeError: module 'looptime' has no attribute 'Looper'
cause Incorrect import: from looptime import looptime or misspelled class name.
fix
Use 'from looptime import Looper' (capital L).
error RuntimeError: Cannot change event loop time outside of looptime context
cause Calling advance() or other time manipulation methods without first entering a Looper context.
fix
Wrap the code in 'async with Looper():' before calling advance().
gotcha Looper must be used as a context manager (async with). Simply creating a Looper instance without entering will not affect event loop timing.
fix Use 'async with Looper() as looper:' to ensure the looper is properly activated.
gotcha Advancing time via looper.advance() does not automatically wake up tasks; it only moves the clock. Tasks waiting on asyncio.sleep() will only resume when the looper's event loop cycle runs (e.g., after the advance call returns).
fix After calling advance(), await asyncio.sleep(0) to yield control and allow scheduled tasks to run.

Basic usage: create a Looper, enter it as a context manager, advance time, and exit.

import asyncio
from looptime import Looper

async def test_sleep():
    looper = Looper()
    asyncio.get_event_loop().run_until_complete(looper.__aenter__())
    await asyncio.sleep(3600)
    # Without looper, this would block for an hour.
    looper.advance(3600)
    # Now the sleep completes immediately.
    await looper.__aexit__(None, None, None)