[issue46771] Add some form of cancel scopes

Andrew Svetlov report at bugs.python.org
Wed Feb 23 10:37:54 EST 2022


Andrew Svetlov <andrew.svetlov at gmail.com> added the comment:

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.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46771>
_______________________________________


More information about the Python-bugs-list mailing list