Message 413812 - Python tracker (original) (raw)

I have no good simple real-case scenario, sorry.

There is a demonstration of my thoughts.

Suppose we have a custom context manager that behaves similar to timeout() but is controlled not by timer but external event source (it could be an invalidation message sent by a distributed broker or something else).

class EventRaised(Exception): pass

class CancelOnEvent: async def init(self, event): self.event = event

async def __aenter__(self):
    self.waiter = asyncio.task(self._cancel_on_event, asyncio.current_task())

async def __aexit__(self, exc_typ, ecx_val, exc_tb):
    if exc_typ is asyncio.CancelledError:
        if CASE1:  # <<< cleanup strategy selector
            if asyncio.current_task().uncancel() == 0:
                raise EventRaised
        else:
            if self.event.is_set():
                raise EventRaised

async def _cancel_on_event(self, task):
    await self.event.wait()
    task.cancel()

########### event = asyncio.Event()

async with asyncio.timeout(1): # what exception should bubble-up here? async with CancelOnEvent(event): await asyncio.sleep(10) # event.set() is called here after 1 sec timeout

If this CancelOnEvent context manager is used together with timeout() CM, is the behavior clear? Should .uncancel() be used by CancelOnEvent? Why? How should it interact with timeout()? I have no clear and obvious answer on these questions, this worries me.