diff --git a/ChangeLog b/ChangeLog index 03e06ec657..86a19daf8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,10 @@ What's New in astroid 2.4.2? ============================ Release Date: TBA +* `FunctionDef.is_generator` properly handles `yield` nodes in `While` tests + + Close PyCQA/pylint#3519 + What's New in astroid 2.4.1? ============================ diff --git a/astroid/node_classes.py b/astroid/node_classes.py index 647272be7a..f064944f76 100644 --- a/astroid/node_classes.py +++ b/astroid/node_classes.py @@ -4500,6 +4500,11 @@ def get_children(self): yield from self.body yield from self.orelse + def _get_yield_nodes_skip_lambdas(self): + """A While node can contain a Yield node in the test""" + yield from self.test._get_yield_nodes_skip_lambdas() + yield from super()._get_yield_nodes_skip_lambdas() + class With( mixins.MultiLineBlockMixin, diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py index de2d151e51..3cd7e723bc 100644 --- a/astroid/scoped_nodes.py +++ b/astroid/scoped_nodes.py @@ -1661,7 +1661,7 @@ def is_generator(self): :returns: True is this is a generator function, False otherwise. :rtype: bool """ - return next(self._get_yield_nodes_skip_lambdas(), False) + return bool(next(self._get_yield_nodes_skip_lambdas(), False)) def infer_call_result(self, caller=None, context=None): """Infer what the function returns when called. diff --git a/tests/unittest_nodes.py b/tests/unittest_nodes.py index 0e8863b868..07733e5fcb 100644 --- a/tests/unittest_nodes.py +++ b/tests/unittest_nodes.py @@ -1335,5 +1335,17 @@ def test_const_itered(): assert [elem.value for elem in itered] == list("string") +def test_is_generator_for_yield_in_while(): + code = """ + def paused_iter(iterable): + while True: + # Continue to yield the same item until `next(i)` or `i.send(False)` + while (yield value): + pass + """ + node = astroid.extract_node(code) + assert bool(node.is_generator()) + + if __name__ == "__main__": unittest.main()