Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Lib/concurrent/futures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
'ALL_COMPLETED',
'CancelledError',
'TimeoutError',
'InvalidStateError',
'BrokenExecutor',
'Future',
'Executor',
Expand Down Expand Up @@ -50,4 +51,4 @@ def __getattr__(name):
ThreadPoolExecutor = te
return te

raise AttributeError(f"module {__name__} has no attribute {name}")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
24 changes: 17 additions & 7 deletions Lib/concurrent/futures/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ class CancelledError(Error):
"""The Future was cancelled."""
pass

class TimeoutError(Error):
"""The operation exceeded the given deadline."""
pass
TimeoutError = TimeoutError # make local alias for the standard exception

class InvalidStateError(Error):
"""The operation is not allowed in this state."""
Expand Down Expand Up @@ -284,7 +282,7 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED):
A named 2-tuple of sets. The first set, named 'done', contains the
futures that completed (is finished or cancelled) before the wait
completed. The second set, named 'not_done', contains uncompleted
futures. Duplicate futures given to *fs* are removed and will be
futures. Duplicate futures given to *fs* are removed and will be
returned only once.
"""
fs = set(fs)
Expand Down Expand Up @@ -312,6 +310,18 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED):
done.update(waiter.finished_futures)
return DoneAndNotDoneFutures(done, fs - done)


def _result_or_cancel(fut, timeout=None):
try:
try:
return fut.result(timeout)
finally:
fut.cancel()
finally:
# Break a reference cycle with the exception in self._exception
del fut


class Future(object):
"""Represents the result of an asynchronous computation."""

Expand Down Expand Up @@ -386,7 +396,7 @@ def done(self):
return self._state in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]

def __get_result(self):
if self._exception:
if self._exception is not None:
try:
raise self._exception
finally:
Expand Down Expand Up @@ -606,9 +616,9 @@ def result_iterator():
while fs:
# Careful not to keep a reference to the popped future
if timeout is None:
yield fs.pop().result()
yield _result_or_cancel(fs.pop())
else:
yield fs.pop().result(end_time - time.monotonic())
yield _result_or_cancel(fs.pop(), end_time - time.monotonic())
finally:
for future in fs:
future.cancel()
Expand Down
Loading
Loading