Skip to content

Commit ffd675d

Browse files
authored
Adjust Calling of Dispatcher.update_persistence (python-telegram-bot#2285)
* Adjust calling of update_persistence (cherry picked from commit 89c522d) * Fix tests and stuff
1 parent 6a831f9 commit ffd675d

File tree

5 files changed

+131
-18
lines changed

5 files changed

+131
-18
lines changed

telegram/ext/defaults.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def tzinfo(self, value: Any) -> NoReturn:
173173
)
174174

175175
@property
176-
def run_async(self) -> Optional[bool]:
176+
def run_async(self) -> bool:
177177
return self._run_async
178178

179179
@run_async.setter

telegram/ext/dispatcher.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,17 @@ def stop(self) -> None:
402402
def has_running_threads(self) -> bool:
403403
return self.running or bool(self.__async_threads)
404404

405-
def process_update(self, update: Union[str, Update, TelegramError]) -> None:
406-
"""Processes a single update.
405+
def process_update(self, update: Any) -> None:
406+
"""Processes a single update and updates the persistence.
407+
408+
Note:
409+
If the update is handled by least one synchronously running handlers (i.e.
410+
``run_async=False`), :meth:`update_persistence` is called *once* after all handlers
411+
synchronous handlers are done. Each asynchronously running handler will trigger
412+
:meth:`update_persistence` on its own.
407413
408414
Args:
409-
update (:obj:`str` | :class:`telegram.Update` | :class:`telegram.TelegramError`):
415+
update (:class:`telegram.Update` | :obj:`object` | :class:`telegram.TelegramError`):
410416
The update to process.
411417
412418
"""
@@ -420,6 +426,8 @@ def process_update(self, update: Union[str, Update, TelegramError]) -> None:
420426
return
421427

422428
context = None
429+
handled = False
430+
sync_modes = []
423431

424432
for group in self.groups:
425433
try:
@@ -428,11 +436,9 @@ def process_update(self, update: Union[str, Update, TelegramError]) -> None:
428436
if check is not None and check is not False:
429437
if not context and self.use_context:
430438
context = CallbackContext.from_update(update, self)
439+
handled = True
440+
sync_modes.append(handler.run_async)
431441
handler.handle_update(update, self, check, context)
432-
433-
# If handler runs async updating immediately doesn't make sense
434-
if not handler.run_async:
435-
self.update_persistence(update=update)
436442
break
437443

438444
# Stop processing with any other handler.
@@ -452,6 +458,16 @@ def process_update(self, update: Union[str, Update, TelegramError]) -> None:
452458
except Exception:
453459
self.logger.exception('An uncaught error was raised while handling the error.')
454460

461+
# Update persistence, if handled
462+
handled_only_async = all(sync_modes)
463+
if handled:
464+
# Respect default settings
465+
if all(mode is DEFAULT_FALSE for mode in sync_modes) and self.bot.defaults:
466+
handled_only_async = self.bot.defaults.run_async
467+
# If update was only handled by async handlers, we don't need to update here
468+
if not handled_only_async:
469+
self.update_persistence(update=update)
470+
455471
def add_handler(self, handler: Handler, group: int = DEFAULT_GROUP) -> None:
456472
"""Register a handler.
457473

tests/test_dispatcher.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
)
3636
from telegram.ext.dispatcher import run_async, Dispatcher, DispatcherHandlerStop
3737
from telegram.utils.deprecate import TelegramDeprecationWarning
38+
from telegram.utils.helpers import DEFAULT_FALSE
3839
from tests.conftest import create_dp
3940
from collections import defaultdict
4041

@@ -804,3 +805,96 @@ def callback(update, context):
804805
assert cdp.persistence.test_flag_bot_data
805806
assert not cdp.persistence.test_flag_user_data
806807
assert cdp.persistence.test_flag_chat_data
808+
809+
def test_update_persistence_once_per_update(self, monkeypatch, dp):
810+
def update_persistence(*args, **kwargs):
811+
self.count += 1
812+
813+
def dummy_callback(*args):
814+
pass
815+
816+
monkeypatch.setattr(dp, 'update_persistence', update_persistence)
817+
818+
for group in range(5):
819+
dp.add_handler(MessageHandler(Filters.text, dummy_callback), group=group)
820+
821+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text=None))
822+
dp.process_update(update)
823+
assert self.count == 0
824+
825+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text='text'))
826+
dp.process_update(update)
827+
assert self.count == 1
828+
829+
def test_update_persistence_all_async(self, monkeypatch, dp):
830+
def update_persistence(*args, **kwargs):
831+
self.count += 1
832+
833+
def dummy_callback(*args, **kwargs):
834+
pass
835+
836+
monkeypatch.setattr(dp, 'update_persistence', update_persistence)
837+
monkeypatch.setattr(dp, 'run_async', dummy_callback)
838+
839+
for group in range(5):
840+
dp.add_handler(
841+
MessageHandler(Filters.text, dummy_callback, run_async=True), group=group
842+
)
843+
844+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text='Text'))
845+
dp.process_update(update)
846+
assert self.count == 0
847+
848+
dp.bot.defaults = Defaults(run_async=True)
849+
try:
850+
for group in range(5):
851+
dp.add_handler(MessageHandler(Filters.text, dummy_callback), group=group)
852+
853+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text='Text'))
854+
dp.process_update(update)
855+
assert self.count == 0
856+
finally:
857+
dp.bot.defaults = None
858+
859+
@pytest.mark.parametrize('run_async', [DEFAULT_FALSE, False])
860+
def test_update_persistence_one_sync(self, monkeypatch, dp, run_async):
861+
def update_persistence(*args, **kwargs):
862+
self.count += 1
863+
864+
def dummy_callback(*args, **kwargs):
865+
pass
866+
867+
monkeypatch.setattr(dp, 'update_persistence', update_persistence)
868+
monkeypatch.setattr(dp, 'run_async', dummy_callback)
869+
870+
for group in range(5):
871+
dp.add_handler(
872+
MessageHandler(Filters.text, dummy_callback, run_async=True), group=group
873+
)
874+
dp.add_handler(MessageHandler(Filters.text, dummy_callback, run_async=run_async), group=5)
875+
876+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text='Text'))
877+
dp.process_update(update)
878+
assert self.count == 1
879+
880+
@pytest.mark.parametrize('run_async,expected', [(DEFAULT_FALSE, 1), (False, 1), (True, 0)])
881+
def test_update_persistence_defaults_async(self, monkeypatch, dp, run_async, expected):
882+
def update_persistence(*args, **kwargs):
883+
self.count += 1
884+
885+
def dummy_callback(*args, **kwargs):
886+
pass
887+
888+
monkeypatch.setattr(dp, 'update_persistence', update_persistence)
889+
monkeypatch.setattr(dp, 'run_async', dummy_callback)
890+
dp.bot.defaults = Defaults(run_async=run_async)
891+
892+
try:
893+
for group in range(5):
894+
dp.add_handler(MessageHandler(Filters.text, dummy_callback), group=group)
895+
896+
update = Update(1, message=Message(1, None, Chat(1, ''), from_user=None, text='Text'))
897+
dp.process_update(update)
898+
assert self.count == expected
899+
finally:
900+
dp.bot.defaults = None

tests/test_jobqueue.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def test_run_monthly(self, job_queue, timezone):
314314
next_months_days = calendar.monthrange(now.year, now.month + 1)[1]
315315

316316
expected_reschedule_time += dtm.timedelta(this_months_days)
317-
if next_months_days < this_months_days:
317+
if day > next_months_days:
318318
expected_reschedule_time += dtm.timedelta(next_months_days)
319319

320320
expected_reschedule_time = timezone.normalize(expected_reschedule_time)

tests/test_message.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,18 +1406,21 @@ def make_assertion(*args, **kwargs):
14061406
def test_default_quote(self, message):
14071407
message.bot.defaults = Defaults()
14081408

1409-
message.bot.defaults._quote = False
1410-
assert message._quote(None, None) is None
1409+
try:
1410+
message.bot.defaults._quote = False
1411+
assert message._quote(None, None) is None
14111412

1412-
message.bot.defaults._quote = True
1413-
assert message._quote(None, None) == message.message_id
1413+
message.bot.defaults._quote = True
1414+
assert message._quote(None, None) == message.message_id
14141415

1415-
message.bot.defaults._quote = None
1416-
message.chat.type = Chat.PRIVATE
1417-
assert message._quote(None, None) is None
1416+
message.bot.defaults._quote = None
1417+
message.chat.type = Chat.PRIVATE
1418+
assert message._quote(None, None) is None
14181419

1419-
message.chat.type = Chat.GROUP
1420-
assert message._quote(None, None)
1420+
message.chat.type = Chat.GROUP
1421+
assert message._quote(None, None)
1422+
finally:
1423+
message.bot.defaults = None
14211424

14221425
def test_equality(self):
14231426
id_ = 1

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy