ASYNC100 (ruff, upstream) warns when a timeout context manager doesn't contain any checkpoints - and therefore can't be cancelled by the async framework. However, if you're implementing a context manager, then it's entirely reasonable to wrap such a timeout around a yield, and we should treat that as a checkpoint - as in python-trio/flake8-async#228
(if you wrap a timeout around the yield in a generator, see PEP-789 and the ASYNC9xx rules, with my condolences)
from contextlib import asynccontextmanager
import anyio
async def bad_code():
with anyio.fail_after(10):
do_something_slow() # can't cancel non-async work!
@asynccontextmanager
async def good_code():
with anyio.fail_after(10):
# There's no await keyword here, but we presume that there
# will be in the caller we yield to, so this is safe.
yield
The current version of Ruff will warn on both fail_after() contexts, but only the former is problematic.
See also: #8451
ASYNC100(ruff, upstream) warns when a timeout context manager doesn't contain any checkpoints - and therefore can't be cancelled by the async framework. However, if you're implementing a context manager, then it's entirely reasonable to wrap such a timeout around ayield, and we should treat that as a checkpoint - as in python-trio/flake8-async#228(if you wrap a timeout around the
yieldin a generator, see PEP-789 and the ASYNC9xx rules, with my condolences)The current version of Ruff will warn on both
fail_after()contexts, but only the former is problematic.See also: #8451