diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/asyncio/base_futures.py | 8 | ||||
-rw-r--r-- | Lib/concurrent/futures/__init__.py | 1 | ||||
-rw-r--r-- | Lib/concurrent/futures/_base.py | 8 | ||||
-rw-r--r-- | Lib/test/test_concurrent_futures.py | 28 |
4 files changed, 39 insertions, 6 deletions
diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py index 5182884e16..bd65beec55 100644 --- a/Lib/asyncio/base_futures.py +++ b/Lib/asyncio/base_futures.py @@ -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. diff --git a/Lib/concurrent/futures/__init__.py b/Lib/concurrent/futures/__init__.py index 8434fcf4b5..d746aeac50 100644 --- a/Lib/concurrent/futures/__init__.py +++ b/Lib/concurrent/futures/__init__.py @@ -10,6 +10,7 @@ from concurrent.futures._base import (FIRST_COMPLETED, ALL_COMPLETED, CancelledError, TimeoutError, + InvalidStateError, BrokenExecutor, Future, Executor, diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 4f22f7ee0e..d4416c6245 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -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): @@ -513,6 +517,8 @@ class Future(object): 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: @@ -526,6 +532,8 @@ class Future(object): 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: diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index b258a0eafd..f2c28ac12b 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -1206,6 +1206,34 @@ class FutureTests(BaseTestCase): 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(): |