From 46f5ca31d0856f5d258d86085047eda296ee9972 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 14 Sep 2013 20:51:57 -0700 Subject: [PATCH] Issue #19018: The heapq.merge() function no longer suppresses IndexError --- Lib/heapq.py | 14 +++++++++----- Lib/test/test_heapq.py | 9 +++++++++ Misc/ACKS | 2 ++ Misc/NEWS | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Lib/heapq.py b/Lib/heapq.py index 00b429c2d36..d615239b946 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -358,6 +358,7 @@ def merge(*iterables): ''' _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration + _len = len h = [] h_append = h.append @@ -369,17 +370,20 @@ def merge(*iterables): pass heapify(h) - while 1: + while _len(h) > 1: try: - while 1: - v, itnum, next = s = h[0] # raises IndexError when h is empty + while True: + v, itnum, next = s = h[0] yield v s[0] = next() # raises StopIteration when exhausted _heapreplace(h, s) # restore heap condition except _StopIteration: _heappop(h) # remove empty iterator - except IndexError: - return + if h: + # fast case when only a single iterator remains + v, itnum, next = h[0] + yield v + yield from next.__self__ # Extend the implementations of nsmallest and nlargest to use a key= argument _nsmallest = nsmallest diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index b48ca684614..b5a2fd803a8 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -158,6 +158,15 @@ class TestHeap: self.assertEqual(sorted(chain(*inputs)), list(self.module.merge(*inputs))) 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): class Int(int): pass diff --git a/Misc/ACKS b/Misc/ACKS index 9781600b2c0..b5ebf0698a2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -133,6 +133,7 @@ Paul Boddie Matthew Boedicker Robin Boerdijk David Bolen +Wouter Bolsterlee Gawain Bolton Forest Bond Gregory Bond @@ -382,6 +383,7 @@ Nils Fischbeck Frederik Fix Matt Fleming Hernán Martínez Foffani +Artem Fokin Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc diff --git a/Misc/NEWS b/Misc/NEWS index 1655238181d..f74cdb19d1e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,9 @@ Library - Issue #17324: Fix http.server's request handling case on trailing '/'. Patch 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, if all necessary functions are already found in libuuid. Patch by Evgeny Sologubov.