Search code examples
pythonmatchgeneratorpylintiterable

Pylint error not-an-iterable in match case


I have 2 functions that do the same thing: recursively iterate an object and return all the string values. I would prefer to use iter2, with the match case, as it is easier on the eye. They both run correctly but pylint reports errors in the second function.

def iter1(object_):
    if isinstance(object_, str):
        yield object_
    if isinstance(object_, list):
        for item in object_:
            yield from iter1(item)
    elif isinstance(object_, dict):
        for value in object_.values():
            yield from iter1(value)
    return

def iter2(object_):
    match object_:
        case str():
            yield object_
        case list():
            for item in object_:
                yield from iter2(item)
        case dict():
            for value in object_.values():
                yield from iter2(value)
        case _:
            return

aaa = {"a": "abc", "b": "123", "c": ["def", "ghi", "jkl"], "d": {"e": "mno", "f": ["pqr", "stu"]}}
print(list(iter1(aaa)))
print(list(iter2(aaa)))

Both produce the same output.

['abc', '123', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu']
['abc', '123', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu']

But pylint reports these errors in the function iter2.

Non-iterable value iter2(item) is used in an iterating context pylint (not-an-iterable)
Non-iterable value iter2(value) is used in an iterating context pylint (not-an-iterable)

at these lines:

yield from iter2(item)
yield from iter2(value)

I have logged it as a bug on pylint's github


Solution

  • This issue has been fixed by Pylint and the not-an-iterable messages are no longer emitted for this code. The fix is available since version 2.17.0 (release date: March 8 2023).