diff options
| author | Serhiy Storchaka <storchaka@gmail.com> | 2024-01-10 10:50:31 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-10 10:50:31 (GMT) |
| commit | aef4a1203c06efde8505aefc9cf994e9a23f398d (patch) | |
| tree | 006ea6c1226b329803c5649eb00b1a6ac1316bf5 /Lib/asyncio/timeouts.py | |
| parent | ab0ad62038317a3d15099c23d2b0f03bee9f8fa7 (diff) | |
| download | cpython-aef4a1203c06efde8505aefc9cf994e9a23f398d.zip cpython-aef4a1203c06efde8505aefc9cf994e9a23f398d.tar.gz cpython-aef4a1203c06efde8505aefc9cf994e9a23f398d.tar.bz2 | |
gh-96037: Always insert TimeoutError when exit an expired asyncio.timeout() block (GH-113819)
If other exception was raised during exiting an expired
asyncio.timeout() block, insert TimeoutError in the exception context
just above the CancelledError.
Diffstat (limited to 'Lib/asyncio/timeouts.py')
| -rw-r--r-- | Lib/asyncio/timeouts.py | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/Lib/asyncio/timeouts.py b/Lib/asyncio/timeouts.py index 2c5dd29..e6f5100 100644 --- a/Lib/asyncio/timeouts.py +++ b/Lib/asyncio/timeouts.py @@ -110,10 +110,15 @@ class Timeout: self._state = _State.EXPIRED if self._task.uncancel() <= self._cancelling and exc_type is not None: + # Since there are no new cancel requests, we're + # handling this. if issubclass(exc_type, exceptions.CancelledError): - # Since there are no new cancel requests, we're - # handling this. raise TimeoutError from exc_val + elif exc_val is not None: + self._insert_timeout_error(exc_val) + if isinstance(exc_val, ExceptionGroup): + for exc in exc_val.exceptions: + self._insert_timeout_error(exc) elif self._state is _State.ENTERED: self._state = _State.EXITED @@ -126,6 +131,16 @@ class Timeout: # drop the reference early self._timeout_handler = None + @staticmethod + def _insert_timeout_error(exc_val: BaseException) -> None: + while exc_val.__context__ is not None: + if isinstance(exc_val.__context__, exceptions.CancelledError): + te = TimeoutError() + te.__context__ = te.__cause__ = exc_val.__context__ + exc_val.__context__ = te + break + exc_val = exc_val.__context__ + def timeout(delay: Optional[float]) -> Timeout: """Timeout async context manager. |
