{"id":21545,"library":"looptime","title":"looptime","description":"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.","status":"active","version":"0.7","language":"python","source_language":"en","source_url":"https://github.com/ariebovenberg/looptime","tags":["asyncio","testing","time","virtual-time","fast-forward"],"install":[{"cmd":"pip install looptime","lang":"bash","label":"PyPI"}],"dependencies":[],"imports":[{"note":"","wrong":"","symbol":"Looper","correct":"from looptime import Looper"}],"quickstart":{"code":"import asyncio\nfrom looptime import Looper\n\nasync def test_sleep():\n    looper = Looper()\n    asyncio.get_event_loop().run_until_complete(looper.__aenter__())\n    await asyncio.sleep(3600)\n    # Without looper, this would block for an hour.\n    looper.advance(3600)\n    # Now the sleep completes immediately.\n    await looper.__aexit__(None, None, None)","lang":"python","description":"Basic usage: create a Looper, enter it as a context manager, advance time, and exit."},"warnings":[{"fix":"Use 'async with Looper() as looper:' to ensure the looper is properly activated.","message":"Looper must be used as a context manager (async with). Simply creating a Looper instance without entering will not affect event loop timing.","severity":"gotcha","affected_versions":"all"},{"fix":"After calling advance(), await asyncio.sleep(0) to yield control and allow scheduled tasks to run.","message":"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).","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-27T00:00:00.000Z","next_check":"2026-07-26T00:00:00.000Z","problems":[{"fix":"Use 'from looptime import Looper' (capital L).","cause":"Incorrect import: from looptime import looptime or misspelled class name.","error":"AttributeError: module 'looptime' has no attribute 'Looper'"},{"fix":"Wrap the code in 'async with Looper():' before calling advance().","cause":"Calling advance() or other time manipulation methods without first entering a Looper context.","error":"RuntimeError: Cannot change event loop time outside of looptime context"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}