pylint-dev/pylint

False positive for `use-yield-from` for generators yielding from iterators

jakelishman opened this issue · 0 comments

Bug description

Within a generator expression, pylint issues use-yield-from for constructs such as:

def my_generator[T, S](iterator: Iterable[T]) -> Generator[T, S, S]:
    for item in iterator:
        state = yield iterator
    return state

When iterator is an Iterator and not a Generator, it will not have the generator methods (e.g. send), so applying Pylint's suggestion will modify the type of my_generator from Generator[T, S, S] to Generator[T, None, None] (and will generally cause AttributeError to be raised on calls to send).

Example file generator.py:

import typing

iterable: list[int] = [1, 2, 3]

def gen1():
    for item in iterable:
        # Implicitly suggesting that `send` will be used.
        _ = yield item

# ... and ...

# Explicitly requiring that `send` must exist.
def gen2() -> typing.Generator[int, object, None]:
    for item in iterable:
        yield item

Configuration

No response

Command used

pylint generator.py

Pylint output

************* Module generator
generator.py:6:4: R1737: Use 'yield from' directly instead of yielding each element one by one (use-yield-from)
generator.py:14:4: R1737: Use 'yield from' directly instead of yielding each element one by one (use-yield-from)

Expected behavior

In many cases, I suspect that the message is worth the risk of the false positive:

def gen():
    for item in iterator:
        yield item

probably should emit the message, but imo neither of my examples in generator.py should, maybe unless iterable could be inferred to be a compatible type (which it explicitly isn't in my example).

Pylint version

pylint 3.2.2
astroid 3.2.2
Python 3.12.0rc3 (main, Sep 21 2023, 17:27:59) [Clang 16.0.6 ]

OS / Environment

No response

Additional dependencies

No response