From a6dbed6dfb07989f064bae5938fb3b67eb144a69 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 4 Feb 2019 12:33:54 +0100 Subject: [PATCH] Add a way to continue the update propagation within a group Add continue_propagation() method and ContinuePropagation exception Closes #212 --- docs/source/resources/MoreOnUpdates.rst | 85 ++++++++++++++++++++++-- pyrogram/__init__.py | 3 +- pyrogram/client/dispatcher/dispatcher.py | 2 + pyrogram/client/types/__init__.py | 2 +- pyrogram/client/types/update.py | 7 ++ 5 files changed, 91 insertions(+), 8 deletions(-) diff --git a/docs/source/resources/MoreOnUpdates.rst b/docs/source/resources/MoreOnUpdates.rst index 44295f35..9712a5d2 100644 --- a/docs/source/resources/MoreOnUpdates.rst +++ b/docs/source/resources/MoreOnUpdates.rst @@ -91,13 +91,14 @@ Stop Propagation In order to prevent further propagation of an update in the dispatching phase, you can do *one* of the following: - Call the update's bound-method ``.stop_propagation()`` (preferred way). -- Manually ``raise StopPropagation`` error (more suitable for raw updates only). +- Manually ``raise StopPropagation`` exception (more suitable for raw updates only). .. note:: - Note that ``.stop_propagation()`` is just an elegant and intuitive way to raise a ``StopPropagation`` error; - this means that any code coming *after* calling it won't be executed as your function just raised a custom exception - to signal the dispatcher not to propagate the update anymore. + Internally, the propagation is stopped by handling a custom exception. ``.stop_propagation()`` is just an elegant + and intuitive way to ``raise StopPropagation``; this also means that any code coming *after* calling the method + won't be executed as your function just raised an exception to signal the dispatcher not to propagate the + update anymore. Example with ``stop_propagation()``: @@ -139,10 +140,82 @@ Example with ``raise StopPropagation``: def _(client, message): print(2) -The handler in group number 2 will never be executed because the propagation was stopped before. The output of both -examples will be: +Each handler is registered in a different group, but the handler in group number 2 will never be executed because the +propagation was stopped earlier. The output of both (equivalent) examples will be: .. code-block:: text 0 1 + +Continue Propagation +^^^^^^^^^^^^^^^^^^^^ + +As opposed to `stopping the update propagation <#stop-propagation>`_ and also as an alternative to the +`handler groups <#handler-groups>`_, you can signal the internal dispatcher to continue the update propagation within +the group regardless of the next handler's filters. This allows you to register multiple handlers with overlapping +filters in the same group; to let the dispatcher process the next handler you can do *one* of the following in each +handler you want to grant permission to continue: + +- Call the update's bound-method ``.continue_propagation()`` (preferred way). +- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only). + +.. note:: + + Internally, the propagation is continued by handling a custom exception. ``.continue_propagation()`` is just an + elegant and intuitive way to ``raise ContinuePropagation``; this also means that any code coming *after* calling the + method won't be executed as your function just raised an exception to signal the dispatcher to continue with the + next available handler. + + +Example with ``continue_propagation()``: + +.. code-block:: python + + @app.on_message(Filters.private) + def _(client, message): + print(0) + message.continue_propagation() + + + @app.on_message(Filters.private) + def _(client, message): + print(1) + message.continue_propagation() + + + @app.on_message(Filters.private) + def _(client, message): + print(2) + +Example with ``raise ContinuePropagation``: + +.. code-block:: python + + from pyrogram import ContinuePropagation + + @app.on_message(Filters.private) + def _(client, message): + print(0) + raise ContinuePropagation + + + @app.on_message(Filters.private) + def _(client, message): + print(1) + raise ContinuePropagation + + + @app.on_message(Filters.private) + def _(client, message): + print(2) + +Three handlers are registered in the same group, and all of them will be executed because the propagation was continued +in each handler (except in the last one, where is useless to do so since there is no more handlers after). +The output of both (equivalent) examples will be: + +.. code-block:: text + + 0 + 1 + 2 \ No newline at end of file diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index db3d8674..62f74ddf 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -32,7 +32,8 @@ from .client.types import ( Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus, UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, - Poll, PollOption, ChatPreview, StopPropagation, Game, CallbackGame, GameHighScore, GameHighScores + Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation, Game, CallbackGame, GameHighScore, + GameHighScores ) from .client import ( Client, ChatAction, ParseMode, Emoji, diff --git a/pyrogram/client/dispatcher/dispatcher.py b/pyrogram/client/dispatcher/dispatcher.py index cb22a48c..5a463077 100644 --- a/pyrogram/client/dispatcher/dispatcher.py +++ b/pyrogram/client/dispatcher/dispatcher.py @@ -151,6 +151,8 @@ class Dispatcher: handler.callback(self.client, *args) except pyrogram.StopPropagation: raise + except pyrogram.ContinuePropagation: + continue except Exception as e: log.error(e, exc_info=True) diff --git a/pyrogram/client/types/__init__.py b/pyrogram/client/types/__init__.py index ca332a22..a29b0816 100644 --- a/pyrogram/client/types/__init__.py +++ b/pyrogram/client/types/__init__.py @@ -30,7 +30,7 @@ from .messages_and_media import ( Sticker, Venue, Video, VideoNote, Voice, UserProfilePhotos, Message, Messages, MessageEntity, Poll, PollOption, Game ) -from .update import StopPropagation +from .update import StopPropagation, ContinuePropagation from .user_and_chats import ( Chat, ChatMember, ChatMembers, ChatPhoto, Dialog, Dialogs, User, UserStatus, ChatPreview diff --git a/pyrogram/client/types/update.py b/pyrogram/client/types/update.py index 80c233c0..2ec22f5a 100644 --- a/pyrogram/client/types/update.py +++ b/pyrogram/client/types/update.py @@ -21,6 +21,13 @@ class StopPropagation(StopIteration): pass +class ContinuePropagation(StopIteration): + pass + + class Update: def stop_propagation(self): raise StopPropagation + + def continue_propagation(self): + raise ContinuePropagation