]> arthur.barton.de Git - bup.git/commitdiff
merge_iter: don't compare generators with < via heapq
authorRob Browning <rlb@defaultvalue.org>
Fri, 18 Oct 2019 04:22:59 +0000 (23:22 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sun, 15 Dec 2019 20:59:15 +0000 (14:59 -0600)
Previously we were implicitly comparing (entry, reader_generator) with
"<" in the merge_iter heapq.  In python 2, the generators would just
compare as pointers, which was fine, because we only cared about the
ordering of the initial entries.

However, in Python 3 comparing generators provokes a TypeError, so
create a trivial helper class that can carry the two items, but only
compare the entries via the < operator.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/helpers.py

index 64d5b26bfcbdf7d5e919f247819ac313a3486174..3aea8b1b11318c8860a3fd26248a439f057fcff0 100644 (file)
@@ -214,6 +214,13 @@ def mkdirp(d, mode=None):
             raise
 
 
+class MergeIterItem:
+    def __init__(self, entry, read_it):
+        self.entry = entry
+        self.read_it = read_it
+    def __lt__(self, x):
+        return self.entry < x.entry
+
 def merge_iter(iters, pfreq, pfunc, pfinal, key=None):
     if key:
         samekey = lambda e, pe: getattr(e, key) == getattr(pe, key, None)
@@ -223,14 +230,14 @@ def merge_iter(iters, pfreq, pfunc, pfinal, key=None):
     total = sum(len(it) for it in iters)
     iters = (iter(it) for it in iters)
     heap = ((next(it, None),it) for it in iters)
-    heap = [(e,it) for e,it in heap if e]
+    heap = [MergeIterItem(e, it) for e, it in heap if e]
 
     heapq.heapify(heap)
     pe = None
     while heap:
         if not count % pfreq:
             pfunc(count, total)
-        e, it = heap[0]
+        e, it = heap[0].entry, heap[0].read_it
         if not samekey(e, pe):
             pe = e
             yield e
@@ -240,7 +247,8 @@ def merge_iter(iters, pfreq, pfunc, pfinal, key=None):
         except StopIteration:
             heapq.heappop(heap) # remove current
         else:
-            heapq.heapreplace(heap, (e, it)) # shift current to new location
+            # shift current to new location
+            heapq.heapreplace(heap, MergeIterItem(e, it))
     pfinal(count, total)