Skip to content

Commit

Permalink
Add the remaining property #20 (#21)
Browse files Browse the repository at this point in the history
- If timeout is not started yet or started unconstrained: remaining is None
- If timeout is expired: remaining is 0.0
- All other: roughly amount of time before TimeoutError is triggered
  • Loading branch information
Kentzo authored and asvetlov committed Sep 9, 2017
1 parent cc315ee commit 31dd718
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
12 changes: 10 additions & 2 deletions async_timeout/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def __init__(self, timeout, *, loop=None):
self._task = None
self._cancelled = False
self._cancel_handler = None
self._cancel_at = None

def __enter__(self):
return self._do_enter()
Expand All @@ -47,14 +48,21 @@ def __aexit__(self, exc_type, exc_val, exc_tb):
def expired(self):
return self._cancelled

@property
def remaining(self):
if self._cancel_at is not None:
return max(self._cancel_at - self._loop.time(), 0.0)
else:
return None

def _do_enter(self):
if self._timeout is not None:
self._task = current_task(self._loop)
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)
self._cancel_at = self._loop.time() + self._timeout
self._cancel_handler = self._loop.call_at(self._cancel_at, self._cancel_task)
return self

def _do_exit(self, exc_type):
Expand Down
18 changes: 18 additions & 0 deletions tests/test_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,21 @@ def test_timeout_inner_other_error(loop):
with timeout(0.01, loop=loop) as cm:
raise RuntimeError
assert not cm.expired

@asyncio.coroutine
def test_timeout_remaining(loop):
with timeout(None, loop=loop) as cm:
assert cm.remaining is None

t = timeout(1.0, loop=loop)
assert t.remaining is None

with timeout(1.0, loop=loop) as cm:
yield from asyncio.sleep(0.1, loop=loop)
assert cm.remaining < 1.0

with pytest.raises(asyncio.TimeoutError):
with timeout(0.1, loop=loop) as cm:
yield from asyncio.sleep(0.5, loop=loop)

assert cm.remaining == 0.0

0 comments on commit 31dd718

Please sign in to comment.