python-trio / flake8-async

Highly opinionated linter for Trio code
https://flake8-async.readthedocs.io
MIT License
17 stars 2 forks source link

TRIO100 false positive with an async CM #200

Closed mikenerone closed 4 months ago

mikenerone commented 4 months ago
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager

import trio

@asynccontextmanager
async def a_cm_can_start_a_nursery() -> AsyncGenerator[None]:
    async with trio.open_nursery() as nursery:
        nursery.start_soon(trio.sleep_forever)
        yield

async def main() -> None:
    # ↓↓↓↓↓ TRIO100 A `with trio.CancelScope(...):` context does not contain any `await` statements. This makes it pointless, as the timeout can only be triggered by a checkpoint.
    with trio.CancelScope() as cancel_scope:
        async with a_cm_can_start_a_nursery():
            try:
                pass # Pretend there's some real logic
            finally:
                # Body exiting. For all I know, the CM has nursery like this one does. If so, I need it cancelled.
                cancel_scope.cancel()

trio.run(main)

The logic and wording of TRIO100 are both incorrect. The above is a valid case for a cancel scope with no awaits in the body. Without the cancel(), this hangs forever instead of exiting.

mikenerone commented 4 months ago

My bad, this is a case of ruff being outdated. This is already fixed in flake8-trio.