Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b991597

Browse files
committed
Issue #20367: Fix behavior of concurrent.futures.as_completed() for duplicate
arguments. Patch by Glenn Langford.
1 parent d1c85fd commit b991597

5 files changed

Lines changed: 17 additions & 3 deletions

File tree

Doc/library/concurrent.futures.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,8 @@ Module Functions
368368

369369
Returns an iterator over the :class:`Future` instances (possibly created by
370370
different :class:`Executor` instances) given by *fs* that yields futures as
371-
they complete (finished or were cancelled). Any futures that completed
371+
they complete (finished or were cancelled). Any futures given by *fs* that
372+
are duplicated will be returned once. Any futures that completed
372373
before :func:`as_completed` is called will be yielded first. The returned
373374
iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
374375
called and the result isn't available after *timeout* seconds from the

Lib/concurrent/futures/_base.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ def as_completed(fs, timeout=None):
181181
182182
Returns:
183183
An iterator that yields the given Futures as they complete (finished or
184-
cancelled).
184+
cancelled). If any given Futures are duplicated, they will be returned
185+
once.
185186
186187
Raises:
187188
TimeoutError: If the entire result iterator could not be generated
@@ -190,11 +191,12 @@ def as_completed(fs, timeout=None):
190191
if timeout is not None:
191192
end_time = timeout + time.time()
192193

194+
fs = set(fs)
193195
with _AcquireFutures(fs):
194196
finished = set(
195197
f for f in fs
196198
if f._state in [CANCELLED_AND_NOTIFIED, FINISHED])
197-
pending = set(fs) - finished
199+
pending = fs - finished
198200
waiter = _create_and_install_waiters(fs, _AS_COMPLETED)
199201

200202
try:

Lib/test/test_concurrent_futures.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,13 @@ def test_zero_timeout(self):
344344
SUCCESSFUL_FUTURE]),
345345
completed_futures)
346346

347+
def test_duplicate_futures(self):
348+
# Issue 20367. Duplicate futures should not raise exceptions or give
349+
# duplicate responses.
350+
future1 = self.executor.submit(time.sleep, 2)
351+
completed = [f for f in futures.as_completed([future1,future1])]
352+
self.assertEqual(len(completed), 1)
353+
347354

348355
class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests, unittest.TestCase):
349356
pass

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ Ronan Lamy
703703
Torsten Landschoff
704704
Łukasz Langa
705705
Tino Lange
706+
Glenn Langford
706707
Andrew Langmead
707708
Detlef Lannert
708709
Soren Larsen

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ Core and Builtins
5050
Library
5151
-------
5252

53+
- Issue #20367: Fix behavior of concurrent.futures.as_completed() for
54+
duplicate arguments. Patch by Glenn Langford.
55+
5356
- Issue #8260: The read(), readline() and readlines() methods of
5457
codecs.StreamReader returned incomplete data when were called after
5558
readline() or read(size). Based on patch by Amaury Forgeot d'Arc.

0 commit comments

Comments
 (0)