diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index be03975a145..a88771af797 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -460,7 +460,7 @@ class Timeout: ... await r.text() - :param timeout: timeout value in seconds + :param timeout: timeout value in seconds or None to disable timeout logic :param loop: asyncio compatible event loop """ def __init__(self, timeout, *, loop=None): @@ -477,8 +477,9 @@ def __enter__(self): if self._task is None: raise RuntimeError('Timeout context manager should be used ' 'inside a task') - self._cancel_handler = self._loop.call_later( - self._timeout, self._cancel_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): @@ -486,8 +487,9 @@ def __exit__(self, exc_type, exc_val, exc_tb): self._cancel_handler = None self._task = None raise asyncio.TimeoutError - self._cancel_handler.cancel() - self._cancel_handler = None + if self._timeout is not None: + self._cancel_handler.cancel() + self._cancel_handler = None self._task = None def _cancel_task(self): diff --git a/tests/test_timeout.py b/tests/test_timeout.py index 7f7b46d0c48..492da30cc22 100644 --- a/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -50,6 +50,18 @@ def run(): loop.run_until_complete(run()) +@pytest.mark.run_loop +def test_timeout_disable(loop): + @asyncio.coroutine + def long_running_task(): + yield from asyncio.sleep(0.1, loop=loop) + return 'done' + + with Timeout(None, loop=loop): + resp = yield from long_running_task() + assert resp == 'done' + + @pytest.mark.run_loop def test_timeout_not_relevant_exception(loop): yield from asyncio.sleep(0, loop=loop)