From 0b662f3b043907e872e49931201dc0fd923c63dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joscha=20G=C3=B6tzer?= Date: Tue, 27 Feb 2018 11:30:42 +0100 Subject: [PATCH] Support stopping propagation of events (#622) --- .../extra/basic/working-with-updates.rst | 27 +++++++++++++++++++ telethon/events/__init__.py | 23 ++++++++++++++++ telethon/telegram_client.py | 10 ++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/readthedocs/extra/basic/working-with-updates.rst b/readthedocs/extra/basic/working-with-updates.rst index a6c0a529..df971d7b 100644 --- a/readthedocs/extra/basic/working-with-updates.rst +++ b/readthedocs/extra/basic/working-with-updates.rst @@ -121,6 +121,33 @@ random number, while if you say ``'eval 4+4'``, you will reply with the solution. Try it! +Stopping propagation of Updates +******************************* + +There might be cases when an event handler is supposed to be used solitary and +it makes no sense to process any other handlers in the chain. For this case, +it is possible to raise a ``StopPropagation`` exception which will cause the +propagation of the update through your handlers to stop: + + .. code-block:: python + + from telethon.events import StopPropagation + + @client.on(events.NewMessage) + def _(event): + # ... some conditions + event.delete() + + # Other handlers won't have an event to work with + raise StopPropagation + + @client.on(events.NewMessage) + def _(event): + # Will never be reached, because it is the second handler + # in the chain. + pass + + Events module ************* diff --git a/telethon/events/__init__.py b/telethon/events/__init__.py index 48b26004..c5c87fbd 100644 --- a/telethon/events/__init__.py +++ b/telethon/events/__init__.py @@ -873,3 +873,26 @@ class MessageChanged(_EventBuilder): self.edited = bool(edit_msg) self.deleted = bool(deleted_ids) self.deleted_ids = deleted_ids or [] + + +class StopPropagation(Exception): + """ + If this Exception is found to be raised in any of the handlers for a + given update, it will stop the execution of all other registered + event handlers in the chain. + Think of it like a ``StopIteration`` exception in a for loop. + + Example usage: + ``` + @client.on(events.NewMessage) + def delete(event): + event.delete() + # Other handlers won't have an event to work with + raise StopPropagation + + @client.on(events.NewMessage) + def _(event): + # Will never be reached, because it is the second handler in the chain. + pass + ``` + """ diff --git a/telethon/telegram_client.py b/telethon/telegram_client.py index a8270aaf..00763000 100644 --- a/telethon/telegram_client.py +++ b/telethon/telegram_client.py @@ -1885,7 +1885,15 @@ class TelegramClient(TelegramBareClient): event = builder.build(update) if event: event._client = self - callback(event) + try: + callback(event) + except events.StopPropagation: + __log__.debug( + "Event handler '{}' stopped chain of " + "propagation for event {}." + .format(callback.__name__, type(event).__name__) + ) + break def add_event_handler(self, callback, event=None): """