Local Python executor ignores loop else clauses (for...else / while...else)
Describe the bug
smolagents.local_python_executor silently ignores the else clause of for
and while loops. In Python, a loop's else block runs when the loop
terminates normally (i.e. the iterator is exhausted or the while condition
becomes false) and is skipped only when the loop is exited via break. The
interpreter's evaluate_for and evaluate_while never look at the loop's
orelse body, so the else block is never executed at all.
Because the executor is what runs CodeAgent-generated code, an agent that
writes a perfectly valid for/else or while/else (a common idiom for search
loops) gets a silently wrong result with no error.
Reproduction
from smolagents.local_python_executor import evaluate_python_code, BASE_PYTHON_TOOLS
code = """
x = 0
for i in range(3):
x += i
else:
x += 100
x
"""
result, _ = evaluate_python_code(code, static_tools=dict(BASE_PYTHON_TOOLS), state={})
print(result) # prints 3 — CPython gives 103The same happens with while ... else. Conversely, when the loop is broken
out of, the else must be skipped (CPython behaviour), which the current code
also cannot express because it returns/exits without distinguishing the two
cases.
Expected behaviour
Match CPython:
- Loop completes normally (no
break) → run theelseblock. - Loop exits via
break→ skip theelseblock. continuedoes not affect whether theelseruns.
Proposed fix
Track whether a break occurred in evaluate_for / evaluate_while, and
execute the loop's orelse body when it did not. Happy to send a small PR with
regression tests.
Source: huggingface/smolagents