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

Skip to content

bpo-33238: Add InvalidStateError to concurrent.futures. #7056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 30, 2018
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
16 changes: 16 additions & 0 deletions Doc/library/concurrent.futures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable.
This method should only be used by :class:`Executor` implementations and
unit tests.

.. versionchanged:: 3.8
This method raises
:exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is
already done.

.. method:: set_exception(exception)

Sets the result of the work associated with the :class:`Future` to the
Expand All @@ -388,6 +393,10 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable.
This method should only be used by :class:`Executor` implementations and
unit tests.

.. versionchanged:: 3.8
This method raises
:exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is
already done.

Module Functions
----------------
Expand Down Expand Up @@ -466,6 +475,13 @@ Exception classes

.. versionadded:: 3.7

.. exception:: InvalidStateError

Raised when an operation is performed on a future that is not allowed
in the current state.

.. versionadded:: 3.8

.. currentmodule:: concurrent.futures.thread

.. exception:: BrokenThreadPool
Expand Down
8 changes: 2 additions & 6 deletions Lib/asyncio/base_futures.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
__all__ = ()

import concurrent.futures._base
import concurrent.futures
import reprlib

from . import format_helpers

Error = concurrent.futures._base.Error
CancelledError = concurrent.futures.CancelledError
TimeoutError = concurrent.futures.TimeoutError


class InvalidStateError(Error):
"""The operation is not allowed in this state."""
InvalidStateError = concurrent.futures.InvalidStateError


# States for Future.
Expand Down
1 change: 1 addition & 0 deletions Lib/concurrent/futures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
ALL_COMPLETED,
CancelledError,
TimeoutError,
InvalidStateError,
BrokenExecutor,
Future,
Executor,
Expand Down
8 changes: 8 additions & 0 deletions Lib/concurrent/futures/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class TimeoutError(Error):
"""The operation exceeded the given deadline."""
pass

class InvalidStateError(Error):
"""The operation is not allowed in this state."""
pass

class _Waiter(object):
"""Provides the event that wait() and as_completed() block on."""
def __init__(self):
Expand Down Expand Up @@ -513,6 +517,8 @@ def set_result(self, result):
Should only be used by Executor implementations and unit tests.
"""
with self._condition:
if self._state in {CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED}:
raise InvalidStateError('{}: {!r}'.format(self._state, self))
self._result = result
self._state = FINISHED
for waiter in self._waiters:
Expand All @@ -526,6 +532,8 @@ def set_exception(self, exception):
Should only be used by Executor implementations and unit tests.
"""
with self._condition:
if self._state in {CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED}:
raise InvalidStateError('{}: {!r}'.format(self._state, self))
self._exception = exception
self._state = FINISHED
for waiter in self._waiters:
Expand Down
28 changes: 28 additions & 0 deletions Lib/test/test_concurrent_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,34 @@ def notification():
self.assertTrue(isinstance(f1.exception(timeout=5), OSError))
t.join()

def test_multiple_set_result(self):
f = create_future(state=PENDING)
f.set_result(1)

with self.assertRaisesRegex(
futures.InvalidStateError,
'FINISHED: <Future at 0x[0-9a-f]+ '
'state=finished returned int>'
):
f.set_result(2)

self.assertTrue(f.done())
self.assertEqual(f.result(), 1)

def test_multiple_set_exception(self):
f = create_future(state=PENDING)
e = ValueError()
f.set_exception(e)

with self.assertRaisesRegex(
futures.InvalidStateError,
'FINISHED: <Future at 0x[0-9a-f]+ '
'state=finished raised ValueError>'
):
f.set_exception(Exception())

self.assertEqual(f.exception(), e)


@test.support.reap_threads
def test_main():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add ``InvalidStateError`` to :mod:`concurrent.futures`.
``Future.set_result`` and ``Future.set_exception`` now raise
``InvalidStateError`` if the futures are not pending or running. Patch by
Jason Haydaman.