Spurious useless-else-on-loop warning

I have a function which uses for ... else, with an early return. Here's a cut down version of it:
"""..."""
def func(c, dt, ct): for cl, op in zip(c.events[0::2], c.events[1::2]): delta = cl.event_datetime - dt if delta > ct: return dt + ct else: dt = op.event_datetime ct -= delta else: return dt
Pylint (1.0.0) complains:
early_exit.py:11: [W0120(useless-else-on-loop), func] Else clause on loop without a break statement
I thought to myself, "self, a return should be treated like a break," and set out to fix this problem. I found the suspect code in checkers/base.py:
def _loop_exits_early(loop): """Returns true if a loop has a break statement in its body.""" loop_nodes = (astroid.For, astroid.While) # Loop over body explicitly to avoid matching break statements # in orelse. for child in loop.body: if isinstance(child, loop_nodes): continue for _ in child.nodes_of_class(astroid.Break, skip_klass=loop_nodes): return True return False
Looking to see where a test case would go, I found test/input/func_useless_else_on_loop.py, with this test case:
def test_return_for(): """else + return is accetable.""" for i in range(10): if i % 2: return i else: print 'math is broken'
Given that _loop_exits_early doesn't check for early returns, how does test_return_for (and test_return_while, not shown) pass when the test suite is run?
I think these two lines belong in _loop_exits_early:
for _ in child.nodes_of_class(astroid.Return, skip_klass=loop_nodes): return True
assuming there is no way to spell that with just a single call to child.nodes_of_class().
(I tried updating my repo, but can't remember my bitbucket password, otherwise I would have checked to see if this problem has already been solved. My apologies if it has.)
Skip

On 9/17/13 2:56 PM, Skip Montanaro wrote:
I have a function which uses for ... else, with an early return. Here's a cut down version of it:
"""..."""
def func(c, dt, ct): for cl, op in zip(c.events[0::2], c.events[1::2]): delta = cl.event_datetime - dt if delta > ct: return dt + ct else: dt = op.event_datetime ct -= delta else: return dt
Pylint (1.0.0) complains:
early_exit.py:11: [W0120(useless-else-on-loop), func] Else clause on loop without a break statement
But this "else" is useless, isn't it? Just put the "return dt" statement after the for statement, no else needed.
--Ned.
participants (2)
-
Ned Batchelder
-
Skip Montanaro