MutaFix run: more-itertools-001

ranker nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B · patcher nvidia/nemotron-3-super-120b-a12b · via Nebius Token Factory

fixedoutcome
48swall time
3model calls
$0.0041API cost
Benchmark ground truth (hidden from the agent)
more_itertools/recipes.py:443 · operator NEGCOND · function more_itertools/recipes.py::partition.<locals>.gen
- while not (queue):   (injected bug)+ while queue:   (original)
retriever rank 1 of 20 · ranker position 1 · patched the right function yes · exact restore yes

Trace

reproduce
+12.45s
3 failing test(s) · 3 failed, 765 passed · 12.45s
failing tests and errors
tests/test_recipes.py::PartitionTests::test_arbitrary
tests/test_recipes.py::PartitionTests::test_bool
tests/test_recipes.py::PartitionTests::test_pred_is_none
tests/test_recipes.py::PartitionTests::test_arbitrary
E   IndexError: pop from an empty deque
tests/test_recipes.py::PartitionTests::test_bool
E   IndexError: pop from an empty deque
trace
+19.63s
re-ran 1 test file(s) with the trace plugin: 3 failing and 145 passing tests, 2 library functions ran in a failing test · 7.11s
tests/test_recipes.py
retrieve
+19.63s
280 functions indexed, 2 reachable from tests/test_recipes.py::PartitionTests::test_arbitrary in the static call graph. Kept 20 candidates, ranked by spectrum score (Ochiai), call graph and BM25 break ties.
candidates in retriever order
  1. more_itertools/recipes.py::partition call depth 1 · Ochiai 1.00 (failing 3, passing 0)
  2. more_itertools/recipes.py::partition.<locals>.gen call depth 1 · Ochiai 1.00 (failing 3, passing 0)
  3. more_itertools/more.py::_extract_buffered call depth - · Ochiai 0.00 (failing 0, passing 0)
  4. more_itertools/recipes.py::iter_except call depth - · Ochiai 0.00 (failing 0, passing 5)
  5. more_itertools/more.py::nth_permutation call depth - · Ochiai 0.00 (failing 0, passing 7)
  6. more_itertools/more.py::last call depth - · Ochiai 0.00 (failing 0, passing 0)
  7. more_itertools/recipes.py::is_prime call depth - · Ochiai 0.00 (failing 0, passing 6)
  8. more_itertools/more.py::numeric_range._get_by_index call depth - · Ochiai 0.00 (failing 0, passing 0)
  9. more_itertools/recipes.py::nth_combination call depth - · Ochiai 0.00 (failing 0, passing 4)
  10. more_itertools/more.py::nth_product call depth - · Ochiai 0.00 (failing 0, passing 0)
  11. more_itertools/recipes.py::_windowed_running_min call depth - · Ochiai 0.00 (failing 0, passing 1)
  12. more_itertools/recipes.py::_windowed_running_max call depth - · Ochiai 0.00 (failing 0, passing 1)
  13. more_itertools/more.py::nth_combination_with_replacement call depth - · Ochiai 0.00 (failing 0, passing 0)
  14. more_itertools/more.py::product_index call depth - · Ochiai 0.00 (failing 0, passing 0)
  15. more_itertools/more.py::first call depth - · Ochiai 0.00 (failing 0, passing 0)
  16. more_itertools/more.py::numeric_range._index_near call depth - · Ochiai 0.00 (failing 0, passing 0)
  17. more_itertools/more.py::_islice_helper call depth - · Ochiai 0.00 (failing 0, passing 0)
  18. more_itertools/more.py::make_decorator call depth - · Ochiai 0.00 (failing 0, passing 0)
  19. more_itertools/recipes.py::all_equal call depth - · Ochiai 0.00 (failing 0, passing 7)
  20. more_itertools/more.py::seekable.__next__ call depth - · Ochiai 0.00 (failing 0, passing 0)
rank
+19.63s
spectrum order kept (no model call)
  1. more_itertools/recipes.py::partition
  2. more_itertools/recipes.py::partition.<locals>.gen
  3. more_itertools/more.py::_extract_buffered
  4. more_itertools/recipes.py::iter_except
  5. more_itertools/more.py::nth_permutation
read
+21.79s
turn 1 · NVIDIA-Nemotron-3-Nano-30B-A3B · 3045 in / 139 out · 2.16s · $0.00022

read more_itertools/recipes.py::partition

The failing tests show an IndexError: pop from an empty deque, which suggests that the code is trying to pop from an empty deque. The issue is likely in the `partition` function or its inner generator function `gen` in the `more_itertools/recipes.py` file. The candidate 1 is the `partition` function, and candidate 2 is the `gen` function inside it. Since the error occurs during popping from the deque, I need to examine the `gen` function more closely to understand the logic that leads to popping from an empty deque.

read
+23.6s
turn 2 · NVIDIA-Nemotron-3-Nano-30B-A3B · 3809 in / 136 out · 1.81s · $0.00026

read more_itertools/recipes.py::partition.<locals>.gen

The failing tests indicate an IndexError when trying to pop from an empty deque. The issue is likely in the `gen` function inside the `partition` function. The `gen` function has a logic flaw where it tries to pop from the queue when it's empty, leading to the IndexError. The current logic in the `gen` function is incorrect because it checks `while not (queue)` which is the opposite of what it should be checking to avoid popping from an empty queue. I need to examine the exact logic to understand how to fix it.

patch
+48.08s
turn 3 · nemotron-3-super-120b-a12b · 4126 in / 2677 out · 12.57s · $0.00365

The inner while loop incorrectly tried to pop from the queue when it was empty, causing IndexError. The condition should be 'while queue:' to drain the queue only when it has elements.

--- a/more_itertools/recipes.py+++ b/more_itertools/recipes.py@@ -441,5 +441,5 @@         append_true = true_queue.append         while True:-            while not (queue):+            while queue:                 yield queue.popleft()             for value in iterator:

tests: all tests pass 768 passed

model reasoning (excerpt)
We need to analyze the bug. The `gen` function:

```
def gen(queue):
    append_false = false_queue.append
    append_true = true_queue.append
    while True:
        while not (queue):
            yield queue.popleft()
        for value in iterator:
            (append_true if pred(value) else append_false)(value)
            break
        else:
            return
```

This seems wrong. Let's trace: For each iteration of outer while True, we enter inner while not (queue): meaning while queue is falsy? Actually `not (queue)` returns True if queue is empty (since empty deque is falsy). So while queue is empty, we do `yield queue.popleft()`. But if queue is empty, popleft raises IndexError. That's clearly wrong: they intended to wait until queue is not empty before popping? Actually typical partition recipe: you want to yield items from the queue as they become available, but you need to fill queues by iterating the iterator. The algorithm: two generators that share the same iterator; each generator yields from its own queue; when its queue is empty, it pulls from the iterator, appends to appropriate queue (based on predicate), and then yields if the item belongs to its queue? Wait typical implementation: https://more-itertools.readthedocs.io/en/stable/_modules/more_itertools/recipes.html#partition

Let's recall the actual recipe from more-itertools:

```
def partition(pred, iterable):
    """
    Use a predicate to partition entries into false entries and true entries
    ...

Final patch

--- a/more_itertools/recipes.py+++ b/more_itertools/recipes.py@@ -441,5 +441,5 @@         append_true = true_queue.append         while True:-            while not (queue):+            while queue:                 yield queue.popleft()             for value in iterator: