File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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 :
Original file line number Diff line number Diff 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
348355class ThreadPoolAsCompletedTests (ThreadPoolMixin , AsCompletedTests , unittest .TestCase ):
349356 pass
Original file line number Diff line number Diff line change @@ -703,6 +703,7 @@ Ronan Lamy
703703Torsten Landschoff
704704Łukasz Langa
705705Tino Lange
706+ Glenn Langford
706707Andrew Langmead
707708Detlef Lannert
708709Soren Larsen
Original file line number Diff line number Diff line change @@ -50,6 +50,9 @@ Core and Builtins
5050Library
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.
You can’t perform that action at this time.
0 commit comments