Pylint: stop-iteration-return false positive for next() with non-empty cycle

Created on 6 Apr 2018  路  6Comments  路  Source: PyCQA/pylint

Steps to reproduce

def test_non_empty_cycle():
    yield next(cycle((0,)))

Current behavior

Do not raise StopIteration in generator, use return statement instead (stop-iteration-return)

Expected behavior

This case should not trigger a refactor message as a cycle iterator with a non-empty iterable will never raise StopIteration.

I am not sure if pylint can determine if an iterable is empty, so this might not be fixable.

pylint --version output

No config file found, using default configuration
pylint 1.8.4,
astroid 1.6.3
Python 3.4.5 (default, Dec 11 2017, 14:22:24)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]

bug

All 6 comments

Hi all,

I would like to add the following to this issue, related to #1830.

def func():
    yield next(iter([]), 42)

This should not issue the stop-iteration-return message since the next statement provides a default value.
I observe this behaviour in both pylint 1.8.3 and 1.8.4.

If you prefer, I can also open a separate issue for this.

@pckroon

I'm pretty sure that has been fixed on master branch of pylint, not in any release however. I'll try to backport it for earlier release.

@qb-cea

I think we could at least ignore this message for the infinite generators in itertools (whitelist them). Custom ones would be tricky however.

@brycepg I can indeed confirm that it has been fixed in master. That said, I'm not running into any mission critical issues due to this, so don't worry about it if backporting it is too much effort.
Thanks :)

Apart of keeping a hardcoded list of potential iterators that will never raise StopIteration, I don't see how else we could fix this. I'd say you can disable the message in that particular spot and keep it enabled for the rest of the codebase. It's a bit cumbersome, but can't see a better solution right now.

I still observe this with

pylint 1.9.2, 
astroid 1.6.5
Python 3.6.5 (default, Jun 17 2018, 12:13:06) 

@sam-s
Use next(something, None) instead of just next(something).
The interface for next is "iterator[, default]", and like it is written in the Python documentation:

If default is given, it is returned if the iterator is exhausted, otherwise StopIteration is raised.

source

Was this page helpful?
0 / 5 - 0 ratings