Commit 39659f22 authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #19018: The heapq.merge() function no longer suppresses IndexError

parent bf7e8656
...@@ -366,6 +366,7 @@ def merge(*iterables): ...@@ -366,6 +366,7 @@ def merge(*iterables):
''' '''
_heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration
_len = len
h = [] h = []
h_append = h.append h_append = h.append
...@@ -377,17 +378,21 @@ def merge(*iterables): ...@@ -377,17 +378,21 @@ def merge(*iterables):
pass pass
heapify(h) heapify(h)
while 1: while _len(h) > 1:
try: try:
while 1: while True:
v, itnum, next = s = h[0] # raises IndexError when h is empty v, itnum, next = s = h[0]
yield v yield v
s[0] = next() # raises StopIteration when exhausted s[0] = next() # raises StopIteration when exhausted
_heapreplace(h, s) # restore heap condition _heapreplace(h, s) # restore heap condition
except _StopIteration: except _StopIteration:
_heappop(h) # remove empty iterator _heappop(h) # remove empty iterator
except IndexError: if h:
return # fast case when only a single iterator remains
v, itnum, next = h[0]
yield v
for v in next.__self__:
yield v
# Extend the implementations of nsmallest and nlargest to use a key= argument # Extend the implementations of nsmallest and nlargest to use a key= argument
_nsmallest = nsmallest _nsmallest = nsmallest
......
...@@ -158,6 +158,15 @@ class TestHeap(TestCase): ...@@ -158,6 +158,15 @@ class TestHeap(TestCase):
self.assertEqual(sorted(chain(*inputs)), list(self.module.merge(*inputs))) self.assertEqual(sorted(chain(*inputs)), list(self.module.merge(*inputs)))
self.assertEqual(list(self.module.merge()), []) self.assertEqual(list(self.module.merge()), [])
def test_merge_does_not_suppress_index_error(self):
# Issue 19018: Heapq.merge suppresses IndexError from user generator
def iterable():
s = list(range(10))
for i in range(20):
yield s[i] # IndexError when i > 10
with self.assertRaises(IndexError):
list(self.module.merge(iterable(), iterable()))
def test_merge_stability(self): def test_merge_stability(self):
class Int(int): class Int(int):
pass pass
......
...@@ -110,6 +110,7 @@ Paul Boddie ...@@ -110,6 +110,7 @@ Paul Boddie
Matthew Boedicker Matthew Boedicker
Robin Boerdijk Robin Boerdijk
David Bolen David Bolen
Wouter Bolsterlee
Gawain Bolton Gawain Bolton
Gregory Bond Gregory Bond
Jurjen Bos Jurjen Bos
...@@ -313,6 +314,7 @@ Nils Fischbeck ...@@ -313,6 +314,7 @@ Nils Fischbeck
Frederik Fix Frederik Fix
Matt Fleming Matt Fleming
Hernán Martínez Foffani Hernán Martínez Foffani
Artem Fokin
Arnaud Fontaine Arnaud Fontaine
Michael Foord Michael Foord
Amaury Forgeot d'Arc Amaury Forgeot d'Arc
......
...@@ -35,6 +35,9 @@ Library ...@@ -35,6 +35,9 @@ Library
- Issue #17324: Fix http.server's request handling case on trailing '/'. Patch - Issue #17324: Fix http.server's request handling case on trailing '/'. Patch
contributed by Vajrasky Kok. contributed by Vajrasky Kok.
- Issue #19018: The heapq.merge() function no longer suppresses IndexError
in the underlying iterables.
- Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL, - Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL,
if all necessary functions are already found in libuuid. if all necessary functions are already found in libuuid.
Patch by Evgeny Sologubov. Patch by Evgeny Sologubov.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment