Skip to content

Commit 8aba7d1

Browse files
Fix false positive in use-yield-from when using yield return (#9700) (#9701)
If the return value from `yield` is inspected inline, such as by (augmented) assignment, changing the looped `yield` to `yield from` is very likely to change the semantics of the generator, since there is an implicit use of `generator.send`. Closes #9696 (cherry picked from commit ea73bae) Co-authored-by: Jake Lishman <[email protected]>
1 parent 192727b commit 8aba7d1

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a false positive for ``use-yield-from`` when using the return value from the ``yield`` atom.
2+
3+
Closes #9696

pylint/checkers/refactoring/refactoring_checker.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -1169,21 +1169,24 @@ def visit_yield(self, node: nodes.Yield) -> None:
11691169
if not isinstance(node.value, nodes.Name):
11701170
return
11711171

1172-
parent = node.parent.parent
1172+
loop_node = node.parent.parent
11731173
if (
1174-
not isinstance(parent, nodes.For)
1175-
or isinstance(parent, nodes.AsyncFor)
1176-
or len(parent.body) != 1
1174+
not isinstance(loop_node, nodes.For)
1175+
or isinstance(loop_node, nodes.AsyncFor)
1176+
or len(loop_node.body) != 1
1177+
# Avoid a false positive if the return value from `yield` is used,
1178+
# (such as via Assign, AugAssign, etc).
1179+
or not isinstance(node.parent, nodes.Expr)
11771180
):
11781181
return
11791182

1180-
if parent.target.name != node.value.name:
1183+
if loop_node.target.name != node.value.name:
11811184
return
11821185

11831186
if isinstance(node.frame(), nodes.AsyncFunctionDef):
11841187
return
11851188

1186-
self.add_message("use-yield-from", node=parent, confidence=HIGH)
1189+
self.add_message("use-yield-from", node=loop_node, confidence=HIGH)
11871190

11881191
@staticmethod
11891192
def _has_exit_in_scope(scope: nodes.LocalsDictNodeNG) -> bool:

tests/functional/u/use/use_yield_from.py

+10
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,13 @@ async def async_for_yield(agen):
5757
async def async_yield(agen):
5858
for item in agen:
5959
yield item
60+
61+
62+
# If the return from `yield` is used inline, don't suggest delegation.
63+
64+
def yield_use_send():
65+
for item in (1, 2, 3):
66+
_ = yield item
67+
total = 0
68+
for item in (1, 2, 3):
69+
total += yield item

0 commit comments

Comments
 (0)