This rule raises issues when trio.sleep(0) or anyio.sleep(0) is used instead of the more explicit and descriptive
trio.lowlevel.checkpoint() or anyio.lowlevel.checkpoint().
When using async libraries like trio or anyio, developers sometimes use sleep(0) as a technique to yield
control back to the event loop, allowing other pending tasks to run. While this approach technically works, it obscures the actual intent.
The sleep(0) pattern is confusing because it suggests waiting for a specific duration (which happens to be 0 seconds), when the actual
intention is to create a checkpoint in the code where the current task can yield control to other tasks without any intended delay.
Both trio and anyio provide dedicated functions for this exact purpose: trio.lowlevel.checkpoint() and
anyio.lowlevel.checkpoint(). These functions clearly communicate the intent to create a checkpoint for task switching.
sleep(0) is less self-documenting and can be confusing to other developers who need to
know the non-obvious intent of the code. sleep(0) is not immediately clear to developers reviewing or maintaining the
code. Replace trio.sleep(0) with trio.lowlevel.checkpoint().
import trio
async def main():
await trio.sleep(0) # Noncompliant
trio.run(main)
import trio
async def main():
await trio.lowlevel.checkpoint() # Compliant
trio.run(main)
Replace anyio.sleep(0) with anyio.lowlevel.checkpoint().
import anyio
async def main():
await anyio.sleep(0) # Noncompliant
anyio.run(main)
import anyio
async def main():
await anyio.lowlevel.checkpoint() # Compliant
anyio.run(main)