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

Skip to content

Commit e6994ff

Browse files
committed
Fix issue #20367: concurrent.futures.as_completed() for duplicate arguments.
Patch by Glenn Langford.
1 parent 252fd0c commit e6994ff

4 files changed

Lines changed: 16 additions & 3 deletions

File tree

Doc/library/concurrent.futures.rst

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

372372
Returns an iterator over the :class:`Future` instances (possibly created by
373373
different :class:`Executor` instances) given by *fs* that yields futures as
374-
they complete (finished or were cancelled). Any futures that completed
374+
they complete (finished or were cancelled). Any futures given by *fs* that
375+
are duplicated will be returned once. Any futures that completed
375376
before :func:`as_completed` is called will be yielded first. The returned
376377
iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
377378
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
@@ -350,6 +350,13 @@ def test_zero_timeout(self):
350350
SUCCESSFUL_FUTURE]),
351351
completed_futures)
352352

353+
def test_duplicate_futures(self):
354+
# Issue 20367. Duplicate futures should not raise exceptions or give
355+
# duplicate responses.
356+
future1 = self.executor.submit(time.sleep, 2)
357+
completed = [f for f in futures.as_completed([future1,future1])]
358+
self.assertEqual(len(completed), 1)
359+
353360

354361
class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests, unittest.TestCase):
355362
pass

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Core and Builtins
3636
Library
3737
-------
3838

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

0 commit comments

Comments
 (0)