New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new ASYNC912
rule to warn on missing checkpoint-or-exceptions
#227
Comments
I think the best way of implementing this is to further extend Given that we're piggybacking on 910/911, it should be easy to piggyback on their autofixing as well. |
Oh wait no, the try/except version is already supported by 910/911: async def no_checkpoint():
try:
await trio.sleep("1")
except ValueError:
... gives an ASYNC910 warning. So there's two separate feature requests:
async def does_not_currently_raise_async100():
async with trio.move_on_after(0.1):
while True:
if ...:
await trio.lowlevel.checkpoint() That will likely make ASYNC100 way noisier, so we might make that a separate rule or make the behaviour togglable with an option. |
Current ASYNC910 autofix logic would place the checkpoint outside and after the loop: # input
async def no_checkpoint(): # ASYNC910: 0, "exit", Statement("function definition", lineno)
while bar():
try:
await trio.sleep("1")
except ValueError:
...
# output
async def no_checkpoint(): # ASYNC910: 0, "exit", Statement("function definition", lineno)
while bar():
try:
await trio.sleep("1")
except ValueError:
...
await trio.lowlevel.checkpoint() Which doesn't actually solve the problem 🙃 And there's no check currently that enforces checkpoints-in-loop-bodies (probably not too bad to add?). So while adding an autofix for async100 might be fairly simple, adding a good autofix is less so. |
I'm generally cautious about increasing noise levels - false-alarms are the traditional killer of static analysis tools. Similarly, better IMO to have no autofix than a bad autofix. If in doubt, let's leave this for later. |
It'll be the same logic as other async91x rules, so the same level of false alarms ("way" noisier was perhaps an overstatement). But I can add it as a separate optional rule for now and you can see how noisy it is.
👍 |
yeah, I'm looking forward to (and/or dreading) seeing the results on our code at work... |
Tasks:
|
Per https://trio.readthedocs.io/en/stable/reference-core.html#checkpoints, Trio's own functions unconditionally checkpoint unless an exception is raised, in which case they may or may not checkpoint. Glossing the design goals of
flake8-async
as (1) enforce these conditions in your own code and (2) miscellaneous, to date we've just ignored the possible lack of checkpoints when an exception is raised. In fairness this is a pretty rare pattern; I think it's only bitten me twice at work - though once very badly.I think the ideal situation here is to add a new
ASYNC912
rule, with a correspondingasync912-context-managers=
config option to expand the denylist of context managers presumed to catch exceptions without re-raising them. I think assuming that any context manager might discard an exception is just too noisy for realistic use, although you could set=*
to emulate that if you really wanted to.How to solve this: add
await trio.lowlevel.checkpoint()
to the loop body, outside the try/except or the with block. An autofix would be nice eventually, but this is rare enough that I wouldn't bother unless it's really easy.The text was updated successfully, but these errors were encountered: