From c1cf296de6d2dc18c6d692c9eb0e5c5c278fb938 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Wed, 8 Jun 2016 13:57:03 -0400 Subject: [PATCH] asyncio: Remove asyncio.timeout() context manager. It will probably be added back in Python 3.6, once its compatibility issues are resolved; see [1] for more details. [1] https://mail.python.org/pipermail/async-sig/2016-June/000045.html --- Doc/library/asyncio-task.rst | 16 --- Doc/whatsnew/3.5.rst | 4 - Lib/asyncio/tasks.py | 53 -------- Lib/test/test_asyncio/test_tasks.py | 187 ---------------------------- 4 files changed, 260 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index a1b69c8a66d..de6ee58e920 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -662,22 +662,6 @@ Task functions except CancelledError: res = None -.. function:: timeout(timeout, \*, loop=None) - - Return a context manager that cancels a block on *timeout* expiring:: - - with timeout(1.5): - yield from inner() - - 1. If ``inner()`` is executed faster than in ``1.5`` seconds - nothing happens. - 2. Otherwise ``inner()`` is cancelled internally but - :exc:`asyncio.TimeoutError` is raised outside of - context manager scope. - - Passing ``None`` as *timeout* argument disables the manager logic. - - .. versionadded:: 3.5.2 .. coroutinefunction:: wait(futures, \*, loop=None, timeout=None,\ return_when=ALL_COMPLETED) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index e3e73e4825f..83d5ce694cc 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -835,10 +835,6 @@ Updates in 3.5.2: method to get the current exception handler. (Contributed by Yury Selivanov.) -* New :func:`~asyncio.timeout` context manager to simplify timeouts - handling code. - (Contributed by Andrew Svetlov.) - * New :meth:`StreamReader.readuntil() ` method to read data from the stream until a separator bytes sequence appears. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 81510ba8d49..0cca8e36a59 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -4,7 +4,6 @@ __all__ = ['Task', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'wait', 'wait_for', 'as_completed', 'sleep', 'async', 'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe', - 'timeout', ] import concurrent.futures @@ -737,55 +736,3 @@ def run_coroutine_threadsafe(coro, loop): loop.call_soon_threadsafe(callback) return future - - -def timeout(timeout, *, loop=None): - """A factory which produce a context manager with timeout. - - Useful in cases when you want to apply timeout logic around block - of code or in cases when asyncio.wait_for is not suitable. - - For example: - - >>> with asyncio.timeout(0.001): - ... yield from coro() - - - timeout: timeout value in seconds or None to disable timeout logic - loop: asyncio compatible event loop - """ - if loop is None: - loop = events.get_event_loop() - return _Timeout(timeout, loop=loop) - - -class _Timeout: - def __init__(self, timeout, *, loop): - self._timeout = timeout - self._loop = loop - self._task = None - self._cancelled = False - self._cancel_handler = None - - def __enter__(self): - self._task = Task.current_task(loop=self._loop) - if self._task is None: - raise RuntimeError('Timeout context manager should be used ' - 'inside a task') - if self._timeout is not None: - self._cancel_handler = self._loop.call_later( - self._timeout, self._cancel_task) - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if exc_type is futures.CancelledError and self._cancelled: - self._cancel_handler = None - self._task = None - raise futures.TimeoutError - if self._timeout is not None: - self._cancel_handler.cancel() - self._cancel_handler = None - self._task = None - - def _cancel_task(self): - self._cancelled = self._task.cancel() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 128b7ce9e56..e7fb774fcae 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2260,192 +2260,5 @@ class SleepTests(test_utils.TestCase): self.assertEqual(result, 11) -class TimeoutTests(test_utils.TestCase): - def setUp(self): - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() - self.loop = None - - def test_timeout(self): - canceled_raised = [False] - - @asyncio.coroutine - def long_running_task(): - try: - yield from asyncio.sleep(10, loop=self.loop) - except asyncio.CancelledError: - canceled_raised[0] = True - raise - - @asyncio.coroutine - def go(): - with self.assertRaises(asyncio.TimeoutError): - with asyncio.timeout(0.01, loop=self.loop) as t: - yield from long_running_task() - self.assertIs(t._loop, self.loop) - - self.loop.run_until_complete(go()) - self.assertTrue(canceled_raised[0], 'CancelledError was not raised') - - def test_timeout_finish_in_time(self): - @asyncio.coroutine - def long_running_task(): - yield from asyncio.sleep(0.01, loop=self.loop) - return 'done' - - @asyncio.coroutine - def go(): - with asyncio.timeout(0.1, loop=self.loop): - resp = yield from long_running_task() - self.assertEqual(resp, 'done') - - self.loop.run_until_complete(go()) - - def test_timeout_gloabal_loop(self): - asyncio.set_event_loop(self.loop) - - @asyncio.coroutine - def run(): - with asyncio.timeout(0.1) as t: - yield from asyncio.sleep(0.01) - self.assertIs(t._loop, self.loop) - - self.loop.run_until_complete(run()) - - def test_timeout_not_relevant_exception(self): - @asyncio.coroutine - def go(): - yield from asyncio.sleep(0, loop=self.loop) - with self.assertRaises(KeyError): - with asyncio.timeout(0.1, loop=self.loop): - raise KeyError - - self.loop.run_until_complete(go()) - - def test_timeout_canceled_error_is_converted_to_timeout(self): - @asyncio.coroutine - def go(): - yield from asyncio.sleep(0, loop=self.loop) - with self.assertRaises(asyncio.CancelledError): - with asyncio.timeout(0.001, loop=self.loop): - raise asyncio.CancelledError - - self.loop.run_until_complete(go()) - - def test_timeout_blocking_loop(self): - @asyncio.coroutine - def long_running_task(): - time.sleep(0.05) - return 'done' - - @asyncio.coroutine - def go(): - with asyncio.timeout(0.01, loop=self.loop): - result = yield from long_running_task() - self.assertEqual(result, 'done') - - self.loop.run_until_complete(go()) - - def test_for_race_conditions(self): - fut = asyncio.Future(loop=self.loop) - self.loop.call_later(0.1, fut.set_result('done')) - - @asyncio.coroutine - def go(): - with asyncio.timeout(0.2, loop=self.loop): - resp = yield from fut - self.assertEqual(resp, 'done') - - self.loop.run_until_complete(go()) - - def test_timeout_time(self): - @asyncio.coroutine - def go(): - foo_running = None - - start = self.loop.time() - with self.assertRaises(asyncio.TimeoutError): - with asyncio.timeout(0.1, loop=self.loop): - foo_running = True - try: - yield from asyncio.sleep(0.2, loop=self.loop) - finally: - foo_running = False - - dt = self.loop.time() - start - # tolerate a small delta for slow delta or unstable clocks - self.assertTrue(0.09 < dt < 0.12, dt) - self.assertFalse(foo_running) - - self.loop.run_until_complete(go()) - - def test_timeout_disable(self): - @asyncio.coroutine - def long_running_task(): - yield from asyncio.sleep(0.1, loop=self.loop) - return 'done' - - @asyncio.coroutine - def go(): - t0 = self.loop.time() - with asyncio.timeout(None, loop=self.loop): - resp = yield from long_running_task() - self.assertEqual(resp, 'done') - dt = self.loop.time() - t0 - # tolerate a time delta for clocks with bad resolution - # and slow buildbots - self.assertTrue(0.09 < dt < 0.15, dt) - self.loop.run_until_complete(go()) - - def test_raise_runtimeerror_if_no_task(self): - with self.assertRaises(RuntimeError): - with asyncio.timeout(0.1, loop=self.loop): - pass - - def test_outer_coro_is_not_cancelled(self): - - has_timeout = [False] - - @asyncio.coroutine - def outer(): - try: - with asyncio.timeout(0.001, loop=self.loop): - yield from asyncio.sleep(1, loop=self.loop) - except asyncio.TimeoutError: - has_timeout[0] = True - - @asyncio.coroutine - def go(): - task = asyncio.ensure_future(outer(), loop=self.loop) - yield from task - self.assertTrue(has_timeout[0]) - self.assertFalse(task.cancelled()) - self.assertTrue(task.done()) - - self.loop.run_until_complete(go()) - - def test_cancel_outer_coro(self): - fut = asyncio.Future(loop=self.loop) - - @asyncio.coroutine - def outer(): - fut.set_result(None) - yield from asyncio.sleep(1, loop=self.loop) - - @asyncio.coroutine - def go(): - task = asyncio.ensure_future(outer(), loop=self.loop) - yield from fut - task.cancel() - with self.assertRaises(asyncio.CancelledError): - yield from task - self.assertTrue(task.cancelled()) - self.assertTrue(task.done()) - - self.loop.run_until_complete(go()) - if __name__ == '__main__': unittest.main()