It’s currently difficult to identify a timeout from asyncio.timeout or from other TimeoutError in the context manager body
I’ve seen code in the wild that incorrectly does:
try:
async with asyncio.timeout(1):
await might_raise_timeout_error()
except TimeoutError:
raise SystemFailed("1 second timeout expired")
But it’s possible that might_raise_timeout_error will raise its own TimeoutError for another reason (eg before the 1 second timeout)
I’d like to see an exc flag to asyncio.timeout so you can do:
async with asyncio.timeout(1, exc=SystemFailed("timeout occurred")):
await etc()
Or for move_on_after
async with asyncio.timeout(1, exc=None):
await etc()
Currently the code to do it in consuming code is possible, but it is a bit complicated:
@contextlib.asynccontextmanager
async def move_on_after(timeout):
timed_out = False
try:
async with timeout:
try:
yield
except TimeoutError:
timed_out = True
raise
except TimeoutError as e:
if timed_out:
raise
@contextlib.asynccontextmanager
async def raise_after(timeout, exc):
timed_out = False
try:
async with timeout:
try:
yield
except TimeoutError:
timed_out = True
raise
except TimeoutError as e:
if timed_out:
raise
else if exc is not None:
try:
raise exc from e
finally:
del exc