class BaseWatch: EVENT: typing.Union[typing.Type[ItemNoUpdateEvent], typing.Type[ItemNoChangeEvent]] def __init__(self, name: str, secs: typing.Union[int, float]): self.fut = PendingFuture(self._post_event, secs) self.name: str = name async def _post_event(self): HABApp.core.EventBus.post_event(self.name, self.EVENT(self.name, self.fut.secs)) async def __cancel_watch(self): self.fut.cancel() log.debug( f'Canceled {self.__class__.__name__} ({self.fut.secs}s) for {self.name}' ) def cancel(self): """Cancel the item watch""" asyncio.run_coroutine_threadsafe(self.__cancel_watch(), loop) def listen_event( self, callback: typing.Callable[[typing.Any], typing.Any] ) -> 'HABApp.core.EventBusListener': """Listen to (only) the event that is emitted by this watcher""" rule = HABApp.rule.get_parent_rule() cb = HABApp.core.WrappedFunction(callback, name=rule._get_cb_name(callback)) listener = EventFilter(self.EVENT, seconds=self.fut.secs).create_event_listener( self.name, cb) return rule._add_event_listener(listener)
class BaseWatch: EVENT: typing.Union[typing.Type[ItemNoUpdateEvent], typing.Type[ItemNoChangeEvent]] def __init__(self, name: str, secs: typing.Union[int, float]): self._fut = PendingFuture(self._post_event, secs) self._name: str = name async def _post_event(self): HABApp.core.EventBus.post_event(self._name, self.EVENT(self._name, self._fut.secs)) async def __cancel_watch(self): self._fut.cancel() def cancel(self): """Cancel the item watch""" asyncio.run_coroutine_threadsafe(self.__cancel_watch(), loop)
async def test_pending_future_cancel(): exception = None async def b(): nonlocal exception try: await asyncio.sleep(200) except Exception as e: exception = e p = PendingFuture(b, 0) p.reset() await asyncio.sleep(0.01) p.reset() await asyncio.sleep(0.01) if sys.version_info[:2] != (3, 8): assert isinstance(exception, asyncio.CancelledError) p.cancel()
async def test_pending_future_cancel(): exception = None async def b(): nonlocal exception try: await asyncio.sleep(200) except BaseException as e: exception = e p = PendingFuture(b, 0) p.reset() await asyncio.sleep(0.05) p.reset() await asyncio.sleep(0.05) p.cancel() assert exception is not None assert isinstance(exception, asyncio.CancelledError)