diff --git a/CHANGES b/CHANGES index 1077203d..ffd0e35f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,34 @@ CHANGES ------- +10/16/2016 Added an expired attribute to TaskTimeout exceptions + that more precisely indicates whether or not the + specified time internal has elapsed. For example: + + try: + await timeout_after(20, coro()) + except TaskTimeout as e: + if e.expired: + # 20 seconds have elapsed. + ... + else: + # Timeout has occurred early + + A premature timeout can occur when timeouts are nested. + For example: + + async with timeout_after(15): + statements + ... + try: + await timeout_after(5, coro()) + except TaskTimeout as e: + if e.expired: + # Inner timeout expired + else: + # Outer timeout must have expired + ... + + 08/16/2016 Modified the Queue class so that the put() method can be used from either synchronous or asynchronous code. For example: diff --git a/curio/kernel.py b/curio/kernel.py index 74a357a8..e3d7f246 100644 --- a/curio/kernel.py +++ b/curio/kernel.py @@ -259,7 +259,7 @@ def _reschedule_task(task, value=None, exc=None): # and continue to run to perform cleanup actions. However, it would # normally terminate shortly afterwards. This method is also used to # raise timeouts. - def _cancel_task(task, exc=CancelledError): + def _cancel_task(task, exc=CancelledError, val=None): if task.terminated: return True @@ -286,7 +286,7 @@ def _cancel_task(task, exc=CancelledError): task.cancel_func() # Reschedule it with a pending exception - _reschedule_task(task, exc=exc(exc.__name__)) + _reschedule_task(task, exc=exc(exc.__name__ if val is None else val)) return True # Cleanup task. This is called after the underlying coroutine has @@ -592,7 +592,7 @@ def _trap_get_current(_): _reschedule_task(task, value=current_time) else: if tm == task.timeout: - if (_cancel_task(task, exc=TaskTimeout)): + if (_cancel_task(task, exc=TaskTimeout, val=current_time)): task.timeout = None else: # Note: There is a possibility that a task will be diff --git a/curio/task.py b/curio/task.py index 63f0f5bc..c4a8132d 100644 --- a/curio/task.py +++ b/curio/task.py @@ -230,6 +230,7 @@ async def __aenter__(self): async def __aexit__(self, ty, val, tb): await _unset_timeout(self._prior) if ty == TaskTimeout: + val.expired = val.args[0] >= self._clock self.result = self._timeout_result if self._ignore: return True @@ -238,7 +239,8 @@ async def _timeout_after_func(clock, coro, ignore=False, timeout_result=None): prior = await _set_timeout(clock) try: return await coro - except TaskTimeout: + except TaskTimeout as e: + e.expired = e.args[0] >= clock if not ignore: raise return timeout_result