[Python-checkins] cpython (3.3): Issue #19018: The heapq.merge() function no longer suppresses IndexError

raymond.hettinger python-checkins at python.org
Sun Sep 15 05:53:11 CEST 2013


http://hg.python.org/cpython/rev/0ff5bb61c6a1
changeset:   85709:0ff5bb61c6a1
branch:      3.3
parent:      85705:63b43935964f
user:        Raymond Hettinger <python at rcn.com>
date:        Sat Sep 14 20:51:57 2013 -0700
summary:
  Issue #19018: The heapq.merge() function no longer suppresses IndexError

files:
  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
--- a/Lib/heapq.py
+++ b/Lib/heapq.py
@@ -358,6 +358,7 @@
 
     '''
     _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration
+    _len = len
 
     h = []
     h_append = h.append
@@ -369,17 +370,20 @@
             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
--- a/Lib/test/test_heapq.py
+++ b/Lib/test/test_heapq.py
@@ -158,6 +158,15 @@
         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
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -133,6 +133,7 @@
 Matthew Boedicker
 Robin Boerdijk
 David Bolen
+Wouter Bolsterlee
 Gawain Bolton
 Forest Bond
 Gregory Bond
@@ -382,6 +383,7 @@
 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
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -72,6 +72,9 @@
 - 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.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list