From d2e6504c5618a81edc9fe84877f4756dc0f71d20 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 19 Apr 2023 21:40:57 +0200 Subject: [PATCH] Fix false 91x alarm on await in genexp target. --- flake8_trio/visitors/visitor91x.py | 6 ++++-- tests/autofix_files/trio910.py | 16 ++++++++++++++++ tests/autofix_files/trio910.py.diff | 5 +++++ tests/eval_files/trio910.py | 15 +++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/flake8_trio/visitors/visitor91x.py b/flake8_trio/visitors/visitor91x.py index 973cf29e..64f13199 100644 --- a/flake8_trio/visitors/visitor91x.py +++ b/flake8_trio/visitors/visitor91x.py @@ -769,9 +769,11 @@ def visit_CompFor(self, node: cst.CompFor): return False - # We don't have any logic on if generators are guaranteed to unroll, so always - # ignore their content by not visiting subnodes. + # The generator target will be immediately evaluated, but the other + # elements will be lazily evaluated as the generator is consumed so we don't + # visit them as any checkpoints in them are not guaranteed to execute. def visit_GeneratorExp(self, node: cst.GeneratorExp): + node.for_in.iter.visit(self) return False def visit_Import(self, node: cst.Import): diff --git a/tests/autofix_files/trio910.py b/tests/autofix_files/trio910.py index ae4f6d56..fe301a18 100644 --- a/tests/autofix_files/trio910.py +++ b/tests/autofix_files/trio910.py @@ -583,3 +583,19 @@ async def foo_comprehension_2(): # error: 0, "exit", Statement("function defini async def foo_comprehension_3(): [... async for x in bar()] + + +# Issue #714 +# (await x async for y in await z) +# ^ ^ ^ this always runs! +# ^ ^ this might not run +# ^ this might not run + + +async def await_in_gen_target(): + (print(x) for x in await foo()) + + +async def await_everywhere_except_gen_target(): # error: 0, "exit", Statement("function definition", lineno) + (await x async for x in bar()) + await trio.lowlevel.checkpoint() diff --git a/tests/autofix_files/trio910.py.diff b/tests/autofix_files/trio910.py.diff index d563f817..d36009bd 100644 --- a/tests/autofix_files/trio910.py.diff +++ b/tests/autofix_files/trio910.py.diff @@ -205,3 +205,8 @@ async def foo_comprehension_3(): +@@ x,3 x,4 @@ + + async def await_everywhere_except_gen_target(): # error: 0, "exit", Statement("function definition", lineno) + (await x async for x in bar()) ++ await trio.lowlevel.checkpoint() diff --git a/tests/eval_files/trio910.py b/tests/eval_files/trio910.py index 930694ed..87707882 100644 --- a/tests/eval_files/trio910.py +++ b/tests/eval_files/trio910.py @@ -555,3 +555,18 @@ async def foo_comprehension_2(): # error: 0, "exit", Statement("function defini async def foo_comprehension_3(): [... async for x in bar()] + + +# Issue #714 +# (await x async for y in await z) +# ^ ^ ^ this always runs! +# ^ ^ this might not run +# ^ this might not run + + +async def await_in_gen_target(): + (print(x) for x in await foo()) + + +async def await_everywhere_except_gen_target(): # error: 0, "exit", Statement("function definition", lineno) + (await x async for x in bar())