I'm Samuel the human, and I endorse this message.
(written by claude)
Bug description
gh-150750 (merged in 3.14.7 via #150921) changed the result of deque.index when a bound's __index__ mutates the deque.
The change is not mentioned in the NEWS entry, which only describes the free-threading race, and is not covered by a test.
from collections import deque
d = deque([1, 2, 3])
class Grow:
def __index__(self):
d.extend([2, 2, 2])
return -1
print(d.index(2, Grow()))
3.14.6 and earlier raise ValueError: deque.index(x): x not in deque.
3.14.7 prints 5.
Before #150779, stop defaulted to Py_SIZE(deque) read during argument parsing, before the start converter called __index__.
In the example, stop was captured as 3, start=-1 then resolved against the live size 6 to give 5, and start > stop clamped the search to an empty window.
After #150779, deque_index_impl reads the size once, after argument conversion, so both bounds resolve against the mutated size and the search finds the element.
The new behavior is self-consistent (one size snapshot, taken after both converters run) and matches what list.index does, so this is probably fine to keep.
Reporting it because the change is user-visible in a patch release: it may deserve a changelog note and a regression test, or reverting if the old behavior was intended.
Your environment
- CPython versions tested on: 3.14.0, 3.14.2, 3.14.4 (old behavior); 3.14.7, 3.15.0rc1 (new behavior)
- Operating system and architecture: macOS arm64
I'm Samuel the human, and I endorse this message.
(written by claude)
Bug description
gh-150750 (merged in 3.14.7 via #150921) changed the result of
deque.indexwhen a bound's__index__mutates the deque.The change is not mentioned in the NEWS entry, which only describes the free-threading race, and is not covered by a test.
3.14.6 and earlier raise
ValueError: deque.index(x): x not in deque.3.14.7 prints
5.Before #150779,
stopdefaulted toPy_SIZE(deque)read during argument parsing, before thestartconverter called__index__.In the example,
stopwas captured as 3,start=-1then resolved against the live size 6 to give 5, andstart > stopclamped the search to an empty window.After #150779,
deque_index_implreads the size once, after argument conversion, so both bounds resolve against the mutated size and the search finds the element.The new behavior is self-consistent (one size snapshot, taken after both converters run) and matches what
list.indexdoes, so this is probably fine to keep.Reporting it because the change is user-visible in a patch release: it may deserve a changelog note and a regression test, or reverting if the old behavior was intended.
Your environment