summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-01-27 08:11:48 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-01-27 08:11:48 (GMT)
commitb9915973f3522d3feaa862aaacd4d7d269f6fc72 (patch)
treee30a6634ad08bd39d80f606075d763b029b6b40b
parentd1c85fd2835bafa0fde0b95b82b6e0fffd60649a (diff)
downloadcpython-b9915973f3522d3feaa862aaacd4d7d269f6fc72.zip
cpython-b9915973f3522d3feaa862aaacd4d7d269f6fc72.tar.gz
cpython-b9915973f3522d3feaa862aaacd4d7d269f6fc72.tar.bz2
Issue #20367: Fix behavior of concurrent.futures.as_completed() for duplicate
arguments. Patch by Glenn Langford.
-rw-r--r--Doc/library/concurrent.futures.rst3
-rw-r--r--Lib/concurrent/futures/_base.py6
-rw-r--r--Lib/test/test_concurrent_futures.py7
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
5 files changed, 17 insertions, 3 deletions
diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst
index c2f92b3..575b1ea 100644
--- a/Doc/library/concurrent.futures.rst
+++ b/Doc/library/concurrent.futures.rst
@@ -368,7 +368,8 @@ Module Functions
Returns an iterator over the :class:`Future` instances (possibly created by
different :class:`Executor` instances) given by *fs* that yields futures as
- they complete (finished or were cancelled). Any futures that completed
+ they complete (finished or were cancelled). Any futures given by *fs* that
+ are duplicated will be returned once. Any futures that completed
before :func:`as_completed` is called will be yielded first. The returned
iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
called and the result isn't available after *timeout* seconds from the
diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py
index ca3aebd..d45a404 100644
--- a/Lib/concurrent/futures/_base.py
+++ b/Lib/concurrent/futures/_base.py
@@ -181,7 +181,8 @@ def as_completed(fs, timeout=None):
Returns:
An iterator that yields the given Futures as they complete (finished or
- cancelled).
+ cancelled). If any given Futures are duplicated, they will be returned
+ once.
Raises:
TimeoutError: If the entire result iterator could not be generated
@@ -190,11 +191,12 @@ def as_completed(fs, timeout=None):
if timeout is not None:
end_time = timeout + time.time()
+ fs = set(fs)
with _AcquireFutures(fs):
finished = set(
f for f in fs
if f._state in [CANCELLED_AND_NOTIFIED, FINISHED])
- pending = set(fs) - finished
+ pending = fs - finished
waiter = _create_and_install_waiters(fs, _AS_COMPLETED)
try:
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
index 39230e1..04c4c37 100644
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -344,6 +344,13 @@ class AsCompletedTests:
SUCCESSFUL_FUTURE]),
completed_futures)
+ def test_duplicate_futures(self):
+ # Issue 20367. Duplicate futures should not raise exceptions or give
+ # duplicate responses.
+ future1 = self.executor.submit(time.sleep, 2)
+ completed = [f for f in futures.as_completed([future1,future1])]
+ self.assertEqual(len(completed), 1)
+
class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests, unittest.TestCase):
pass
diff --git a/Misc/ACKS b/Misc/ACKS
index ba32f6b..a8bb161 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -703,6 +703,7 @@ Ronan Lamy
Torsten Landschoff
Ɓukasz Langa
Tino Lange
+Glenn Langford
Andrew Langmead
Detlef Lannert
Soren Larsen
diff --git a/Misc/NEWS b/Misc/NEWS
index e8d1a7a..7062211 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -50,6 +50,9 @@ Core and Builtins
Library
-------
+- Issue #20367: Fix behavior of concurrent.futures.as_completed() for
+ duplicate arguments. Patch by Glenn Langford.
+
- Issue #8260: The read(), readline() and readlines() methods of
codecs.StreamReader returned incomplete data when were called after
readline() or read(size). Based on patch by Amaury Forgeot d'Arc.