From 3ce9363d2a727fe87f9dbd621eb75f95a0f957b8 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 18:51:39 +0200 Subject: [PATCH 01/32] Change handlers so context is supported --- telegram/ext/__init__.py | 3 +- telegram/ext/callbackqueryhandler.py | 27 ++++---- telegram/ext/choseninlineresulthandler.py | 24 ++----- telegram/ext/commandhandler.py | 33 +++++---- telegram/ext/context.py | 81 +++++++++++++++++++++++ telegram/ext/handler.py | 53 ++++++++++++--- telegram/ext/inlinequeryhandler.py | 32 ++++----- telegram/ext/messagehandler.py | 18 ++--- telegram/ext/precheckoutqueryhandler.py | 17 ++--- telegram/ext/regexhandler.py | 38 ++++++----- telegram/ext/shippingqueryhandler.py | 17 ++--- telegram/ext/stringcommandhandler.py | 28 ++++---- telegram/ext/stringregexhandler.py | 46 +++++++------ telegram/ext/typehandler.py | 26 +++----- tests/test_commandhandler.py | 2 + 15 files changed, 260 insertions(+), 185 deletions(-) create mode 100644 telegram/ext/context.py diff --git a/telegram/ext/__init__.py b/telegram/ext/__init__.py index 1c69d0b8333..63fd72cb0b8 100644 --- a/telegram/ext/__init__.py +++ b/telegram/ext/__init__.py @@ -18,6 +18,7 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """Extensions over the Telegram Bot API to facilitate bot making""" +from .context import Context from .dispatcher import Dispatcher, DispatcherHandlerStop, run_async from .jobqueue import JobQueue, Job from .updater import Updater @@ -43,4 +44,4 @@ 'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler', 'StringRegexHandler', 'TypeHandler', 'ConversationHandler', 'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue', - 'DispatcherHandlerStop', 'run_async') + 'DispatcherHandlerStop', 'run_async', 'Context') diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index 08b37b93459..b6f7473f6c4 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -90,13 +90,15 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(CallbackQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) if isinstance(pattern, string_types): pattern = re.compile(pattern) @@ -123,15 +125,8 @@ def check_update(self, update): else: return True - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(CallbackQueryHandler, self).collect_optional_args(dispatcher, update) if self.pattern: match = re.match(self.pattern, update.callback_query.data) @@ -139,5 +134,13 @@ def handle_update(self, update, dispatcher): optional_args['groups'] = match.groups() if self.pass_groupdict: optional_args['groupdict'] = match.groupdict() + return optional_args - return self.callback(dispatcher.bot, update, **optional_args) + def collect_additional_context(self, context, update, dispatcher): + if self.pattern: + match = re.match(self.pattern, update.callback_query.data) + + if self.pass_groups: + context.groups = match.groups() + if self.pass_groupdict: + context.groupdict = match.groupdict() diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index 34efea3578a..332796dbeb4 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -20,7 +20,6 @@ from .handler import Handler from telegram import Update -from telegram.utils.deprecate import deprecate class ChosenInlineResultHandler(Handler): @@ -67,13 +66,15 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(ChosenInlineResultHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. @@ -86,20 +87,3 @@ def check_update(self, update): """ return isinstance(update, Update) and update.chosen_inline_result - - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) - - return self.callback(dispatcher.bot, update, **optional_args) - - # old non-PEP8 Handler methods - m = "telegram.ChosenInlineResultHandler." - checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update") - handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update") diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 82e8a40b6cc..f64d9c6129f 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -21,8 +21,8 @@ from future.utils import string_types -from .handler import Handler from telegram import Update +from .handler import Handler class CommandHandler(Handler): @@ -96,13 +96,15 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(CommandHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) if isinstance(command, string_types): self.command = [command.lower()] @@ -129,8 +131,8 @@ def check_update(self, update): :obj:`bool` """ - if (isinstance(update, Update) - and (update.message or update.edited_message and self.allow_edited)): + if (isinstance(update, Update) and + (update.message or update.edited_message and self.allow_edited)): message = update.message or update.edited_message if message.text and message.text.startswith('/') and len(message.text) > 1: @@ -155,19 +157,14 @@ def check_update(self, update): return False - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) - - message = update.message or update.edited_message - + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(CommandHandler, self).collect_optional_args(dispatcher, update) if self.pass_args: + message = update.message or update.edited_message optional_args['args'] = message.text.split()[1:] + return optional_args - return self.callback(dispatcher.bot, update, **optional_args) + def collect_additional_context(self, context, update, dispatcher): + if self.pass_args: + message = update.message or update.edited_message + context.args = message.text.split()[1:] diff --git a/telegram/ext/context.py b/telegram/ext/context.py new file mode 100644 index 00000000000..3c4a64bb03e --- /dev/null +++ b/telegram/ext/context.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# A library that provides a Python interface to the Telegram Bot API +# Copyright (C) 2015-2018 +# Leandro Toledo de Souza +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser Public License for more details. +# +# You should have received a copy of the GNU Lesser Public License +# along with this program. If not, see [http://www.gnu.org/licenses/]. + + +class Context(object): + """ + + Attributes: + bot: + update: + chat_data: + user_data: + groups: + groupdict: + job_queue: + update_queue: + args: + message (:class:`telegram.Message`, optional): New incoming message of any kind - text, + photo, sticker, etc. + edited_message (:class:`telegram.Message`, optional): New version of a message that is + known to the bot and was edited. + channel_post (:class:`telegram.Message`, optional): New incoming channel post of any kind + - text, photo, sticker, etc. + edited_channel_post (:class:`telegram.Message`, optional): New version of a channel post + that is known to the bot and was edited. + inline_query (:class:`telegram.InlineQuery`, optional): New incoming inline query. + chosen_inline_result (:class:`telegram.ChosenInlineResult`, optional): The result of an + inline query that was chosen by a user and sent to their chat partner. + callback_query (:class:`telegram.CallbackQuery`, optional): New incoming callback query. + shipping_query (:class:`telegram.ShippingQuery`, optional): New incoming shipping query. + Only for invoices with flexible price. + pre_checkout_query (:class:`telegram.PreCheckoutQuery`, optional): New incoming + pre-checkout query. Contains full information about checkout + """ + + def __init__(self, update, dispatcher): + self.update = update + self.bot = dispatcher.bot + self.chat_data = None + self.user_data = None + if update is not None: + chat = update.effective_chat + user = update.effective_user + + if chat: + self.chat_data = dispatcher.chat_data[chat.id] + if user: + self.user_data = dispatcher.user_data[user.id] + + self.job_queue = dispatcher.job_queue + self.update_queue = dispatcher.update_queue + + self.message = self.update.message + self.edited_message = self.update.edited_message + self.inline_query = self.update.inline_query + self.chosen_inline_result = self.update.chosen_inline_result + self.callback_query = self.update.callback_query + self.shipping_query = self.update.shipping_query + self.pre_checkout_query = self.update.pre_checkout_query + self.channel_post = self.update.channel_post + self.edited_channel_post = self.update.edited_channel_post + + self.args = None + self.groups = None + self.groupdict = None diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index d529b612853..c15abe87905 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -17,6 +17,12 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the base class for handlers as used by the Dispatcher.""" +import inspect +import sys + +from telegram.ext import Context + +has_follow_wrapped = sys.version_info >= (3, 5) class Handler(object): @@ -63,12 +69,24 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): self.callback = callback self.pass_update_queue = pass_update_queue self.pass_job_queue = pass_job_queue self.pass_user_data = pass_user_data self.pass_chat_data = pass_chat_data + self.use_context = use_context + + if use_context is None: + if has_follow_wrapped: + sig = inspect.signature(callback, follow_wrapped=True) + parameters = [p for p in sig.parameters.values() if p.kind == + inspect.Parameter.POSITIONAL_OR_KEYWORD or + p.kind == inspect.Parameter.POSITIONAL_ONLY] + self.use_context = len(parameters) == 1 + else: + pass def check_update(self, update): """ @@ -87,24 +105,43 @@ def check_update(self, update): def handle_update(self, update, dispatcher): """ This method is called if it was determined that an update should indeed - be handled by this instance. It should also be overridden, but in most - cases call ``self.callback(dispatcher.bot, update)``, possibly along with - optional arguments. To work with the ``ConversationHandler``, this method should return the - value returned from ``self.callback`` + be handled by this instance. Calls ``self.callback(dispatcher.bot, update)``, + along with optional arguments. To work with the ``ConversationHandler``, this method + returns the value returned from ``self.callback``. + Note that it can be overridden if needed by the subclassing handler. Args: update (:obj:`str` | :class:`telegram.Update`): The update to be handled. dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher to collect optional args. """ - raise NotImplementedError - def collect_optional_args(self, dispatcher, update=None): - """Prepares the optional arguments that are the same for all types of handlers. + if self.use_context: + context = Context(update, dispatcher) + self.collect_additional_context(context, update, dispatcher) + return self.callback(context) + else: + optional_args = self.collect_optional_args(dispatcher, update) + + return self.callback(dispatcher.bot, update, **optional_args) + + def collect_additional_context(self, context, update, dispatcher): + """Prepares additional arguments for the context. Override if handler needs. Args: + context (:class:`telegram.ext.Context`): The context. dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. + update (:class:`telegram.Update`): The update to gather chat/user id from. + """ + pass + + def collect_optional_args(self, dispatcher, update=None): + """Prepares the optional arguments. If the handler has additional optional args, + it should subclass this method, but remember to call this super method. + Args: + dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. + update (:class:`telegram.Update`): The update to gather chat/user id from. """ optional_args = dict() diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index c5a313d83d3..6d301efecfa 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -22,7 +22,6 @@ from future.utils import string_types from telegram import Update -from telegram.utils.deprecate import deprecate from .handler import Handler @@ -89,13 +88,15 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(InlineQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) if isinstance(pattern, string_types): pattern = re.compile(pattern) @@ -123,16 +124,8 @@ def check_update(self, update): else: return True - def handle_update(self, update, dispatcher): - """ - Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - """ - - optional_args = self.collect_optional_args(dispatcher, update) + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(InlineQueryHandler, self).collect_optional_args(dispatcher, update) if self.pattern: match = re.match(self.pattern, update.inline_query.query) @@ -140,10 +133,13 @@ def handle_update(self, update, dispatcher): optional_args['groups'] = match.groups() if self.pass_groupdict: optional_args['groupdict'] = match.groupdict() + return optional_args - return self.callback(dispatcher.bot, update, **optional_args) + def collect_additional_context(self, context, update, dispatcher): + if self.pattern: + match = re.match(self.pattern, update.inline_query.query) - # old non-PEP8 Handler methods - m = "telegram.InlineQueryHandler." - checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update") - handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update") + if self.pass_groups: + context.groups = match.groups() + if self.pass_groupdict: + context.groupdict = match.groupdict() diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index e9babc31577..a87c447ce23 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -98,7 +98,8 @@ def __init__(self, pass_chat_data=False, message_updates=True, channel_post_updates=True, - edited_updates=False): + edited_updates=False, + use_context=None): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') @@ -111,7 +112,8 @@ def __init__(self, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) self.filters = filters self.message_updates = message_updates self.channel_post_updates = channel_post_updates @@ -155,15 +157,3 @@ def check_update(self, update): res = False return res - - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) - - return self.callback(dispatcher.bot, update, **optional_args) diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index 6f8b3605442..eba709f0a62 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -66,13 +66,15 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(PreCheckoutQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. @@ -85,14 +87,3 @@ def check_update(self, update): """ return isinstance(update, Update) and update.pre_checkout_query - - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) - return self.callback(dispatcher.bot, update, **optional_args) diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 1e83a3eaab6..013c26d72e5 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -106,8 +106,8 @@ def __init__(self, allow_edited=False, message_updates=True, channel_post_updates=False, - edited_updates=False - ): + edited_updates=False, + use_context=None): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') @@ -120,7 +120,8 @@ def __init__(self, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=None) if isinstance(pattern, string_types): pattern = re.compile(pattern) @@ -153,21 +154,22 @@ def check_update(self, update): return bool(match) return False - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(RegexHandler, self).collect_optional_args(dispatcher, update) + if self.pattern: + match = re.match(self.pattern, update.effective_message.text) - optional_args = self.collect_optional_args(dispatcher, update) - match = re.match(self.pattern, update.effective_message.text) + if self.pass_groups: + optional_args['groups'] = match.groups() + if self.pass_groupdict: + optional_args['groupdict'] = match.groupdict() + return optional_args - if self.pass_groups: - optional_args['groups'] = match.groups() - if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + def collect_additional_context(self, context, update, dispatcher): + if self.pattern: + match = re.match(self.pattern, update.effective_message.text) - return self.callback(dispatcher.bot, update, **optional_args) + if self.pass_groups: + context.groups = match.groups() + if self.pass_groupdict: + context.groupdict = match.groupdict() diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index bc374d3be3b..6635fb2f0b1 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -66,13 +66,15 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False): + pass_chat_data=False, + use_context=None): super(ShippingQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data) + pass_chat_data=pass_chat_data, + use_context=use_context) def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. @@ -85,14 +87,3 @@ def check_update(self, update): """ return isinstance(update, Update) and update.shipping_query - - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher, update) - return self.callback(dispatcher.bot, update, **optional_args) diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 9c76ecc4e4a..e0445548368 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -66,9 +66,13 @@ def __init__(self, callback, pass_args=False, pass_update_queue=False, - pass_job_queue=False): + pass_job_queue=False, + use_context=None): super(StringCommandHandler, self).__init__( - callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue) + callback, + pass_update_queue=pass_update_queue, + pass_job_queue=pass_job_queue, + use_context=use_context) self.command = command self.pass_args = pass_args @@ -76,7 +80,7 @@ def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. Args: - update (:obj:`str`): An incomming command. + update (:obj:`str`): An incoming command. Returns: :obj:`bool` @@ -86,18 +90,12 @@ def check_update(self, update): return (isinstance(update, string_types) and update.startswith('/') and update[1:].split(' ')[0] == self.command) - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:obj:`str`): An incomming command. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the command. - - """ - - optional_args = self.collect_optional_args(dispatcher) - + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(StringCommandHandler, self).collect_optional_args(dispatcher, update) if self.pass_args: optional_args['args'] = update.split()[1:] + return optional_args - return self.callback(dispatcher.bot, update, **optional_args) + def collect_additional_context(self, context, update, dispatcher): + if self.pass_args: + context.args = update.split()[1:] diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index f62b3c574d4..786455bc809 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -75,9 +75,13 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_update_queue=False, - pass_job_queue=False): + pass_job_queue=False, + use_contet=None): super(StringRegexHandler, self).__init__( - callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue) + callback, + pass_update_queue=pass_update_queue, + pass_job_queue=pass_job_queue, + use_context=use_contet) if isinstance(pattern, string_types): pattern = re.compile(pattern) @@ -90,7 +94,7 @@ def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. Args: - update (:obj:`str`): An incomming command. + update (:obj:`str`): An incoming command. Returns: :obj:`bool` @@ -98,20 +102,22 @@ def check_update(self, update): """ return isinstance(update, string_types) and bool(re.match(self.pattern, update)) - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:obj:`str`): An incomming command. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the command. - - """ - optional_args = self.collect_optional_args(dispatcher) - match = re.match(self.pattern, update) - - if self.pass_groups: - optional_args['groups'] = match.groups() - if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() - - return self.callback(dispatcher.bot, update, **optional_args) + def collect_optional_args(self, dispatcher, update=None): + optional_args = super(StringRegexHandler, self).collect_optional_args(dispatcher, update) + if self.pattern: + match = re.match(self.pattern, update) + + if self.pass_groups: + optional_args['groups'] = match.groups() + if self.pass_groupdict: + optional_args['groupdict'] = match.groupdict() + return optional_args + + def collect_additional_context(self, context, update, dispatcher): + if self.pattern: + match = re.match(self.pattern, update) + + if self.pass_groups: + context.groups = match.groups() + if self.pass_groupdict: + context.groupdict = match.groupdict() diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index bb388e428b2..2057c51c33b 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -53,10 +53,18 @@ class TypeHandler(Handler): """ - def __init__(self, type, callback, strict=False, pass_update_queue=False, - pass_job_queue=False): + def __init__(self, + type, + callback, + strict=False, + pass_update_queue=False, + pass_job_queue=False, + use_context=None): super(TypeHandler, self).__init__( - callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue) + callback, + pass_update_queue=pass_update_queue, + pass_job_queue=pass_job_queue, + use_context=use_context) self.type = type self.strict = strict @@ -75,15 +83,3 @@ def check_update(self, update): return isinstance(update, self.type) else: return type(update) is self.type - - def handle_update(self, update, dispatcher): - """Send the update to the :attr:`callback`. - - Args: - update (:class:`telegram.Update`): Incoming telegram update. - dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. - - """ - optional_args = self.collect_optional_args(dispatcher) - - return self.callback(dispatcher.bot, update, **optional_args) diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index c8ff4a9569e..7b06b7e1c0a 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -148,6 +148,8 @@ def test_pass_args(self, dp, message): message.text = '/test' dp.process_update(Update(0, message=message)) + import time + time.sleep(.1) assert self.test_flag self.test_flag = False From 714d96df07ba41596b8767ea51552a7e456d9da2 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 19:09:06 +0200 Subject: [PATCH 02/32] Attempt to make parameter "guessing" work on py < 3.5 --- telegram/ext/handler.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index c15abe87905..c666e28cfca 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -23,6 +23,7 @@ from telegram.ext import Context has_follow_wrapped = sys.version_info >= (3, 5) +has_full_argspec = sys.version_info[0] == 3 class Handler(object): @@ -38,6 +39,8 @@ class Handler(object): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -45,6 +48,11 @@ class Handler(object): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -61,6 +69,10 @@ class Handler(object): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ @@ -85,8 +97,12 @@ def __init__(self, inspect.Parameter.POSITIONAL_OR_KEYWORD or p.kind == inspect.Parameter.POSITIONAL_ONLY] self.use_context = len(parameters) == 1 + elif has_full_argspec: + argspec = inspect.getfullargspec(callback) + self.use_context = len(argspec.args) == 1 else: - pass + argspec = inspect.getargspec(callback) + self.use_context = len(argspec.args) == 1 def check_update(self, update): """ From 32a2453f46c9ec3b8009a25613f2304a0723a594 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 19:16:03 +0200 Subject: [PATCH 03/32] Document use_context in all handlers --- telegram/ext/callbackqueryhandler.py | 11 +++++++++++ telegram/ext/choseninlineresulthandler.py | 11 +++++++++++ telegram/ext/commandhandler.py | 11 +++++++++++ telegram/ext/inlinequeryhandler.py | 11 +++++++++++ telegram/ext/messagehandler.py | 11 +++++++++++ telegram/ext/precheckoutqueryhandler.py | 11 +++++++++++ telegram/ext/regexhandler.py | 11 +++++++++++ telegram/ext/shippingqueryhandler.py | 11 +++++++++++ telegram/ext/stringcommandhandler.py | 11 +++++++++++ telegram/ext/stringregexhandler.py | 15 +++++++++++++-- telegram/ext/typehandler.py | 11 +++++++++++ 11 files changed, 123 insertions(+), 2 deletions(-) diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index b6f7473f6c4..84bc19e5bf2 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -47,6 +47,8 @@ class CallbackQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -54,6 +56,11 @@ class CallbackQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -79,6 +86,10 @@ class CallbackQueryHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index 332796dbeb4..39fdf73fcf1 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -35,6 +35,8 @@ class ChosenInlineResultHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -42,6 +44,11 @@ class ChosenInlineResultHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -58,6 +65,10 @@ class ChosenInlineResultHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index f64d9c6129f..00c622a8e35 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -49,6 +49,8 @@ class CommandHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -56,6 +58,11 @@ class CommandHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: command (:obj:`str` | List[:obj:`str`]): The command or list of commands this handler should listen for. @@ -84,6 +91,10 @@ class CommandHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 6d301efecfa..b86df45a446 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -46,6 +46,8 @@ class InlineQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -53,6 +55,11 @@ class InlineQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -78,6 +85,10 @@ class InlineQueryHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ def __init__(self, diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index a87c447ce23..630e7abddef 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -47,6 +47,8 @@ class MessageHandler(Handler): Default is ``False``. allow_edited (:obj:`bool`): Optional. If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -54,6 +56,11 @@ class MessageHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: filters (:class:`telegram.ext.BaseFilter`, optional): A filter inheriting from :class:`telegram.ext.filters.BaseFilter`. Standard filters can be found in @@ -82,6 +89,10 @@ class MessageHandler(Handler): is ``False``. allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. Raises: ValueError diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index eba709f0a62..3f914000127 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -35,6 +35,8 @@ class PreCheckoutQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -42,6 +44,11 @@ class PreCheckoutQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -58,6 +65,10 @@ class PreCheckoutQueryHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 013c26d72e5..7710dad95cb 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -50,6 +50,8 @@ class RegexHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -57,6 +59,11 @@ class RegexHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -88,6 +95,10 @@ class RegexHandler(Handler): is ``False``. allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. Raises: ValueError diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index 6635fb2f0b1..0390c0830d0 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -35,6 +35,8 @@ class ShippingQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -42,6 +44,11 @@ class ShippingQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). + Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. It will be called when the :attr:`check_update` has determined that an update should be @@ -58,6 +65,10 @@ class ShippingQueryHandler(Handler): ``user_data`` will be passed to the callback function. Default is ``False``. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index e0445548368..2012ba2569f 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -39,6 +39,13 @@ class StringCommandHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). Args: @@ -58,6 +65,10 @@ class StringCommandHandler(Handler): ``job_queue`` will be passed to the callback function. It will be a class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index 786455bc809..8bdccb5bc2b 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -46,6 +46,13 @@ class StringRegexHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. @@ -66,6 +73,10 @@ class StringRegexHandler(Handler): ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ @@ -76,12 +87,12 @@ def __init__(self, pass_groupdict=False, pass_update_queue=False, pass_job_queue=False, - use_contet=None): + use_context=None): super(StringRegexHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, - use_context=use_contet) + use_context=use_context) if isinstance(pattern, string_types): pattern = re.compile(pattern) diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index 2057c51c33b..67fb7c615a1 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -33,6 +33,13 @@ class TypeHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to the callback function. + use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + + Note: + Instead of using the individual `pass_` you can use :attr:`use_context` and your callback + function will receive a :class:`telegram.ext.Context` object as the only parameter, + instead of the usual (bot, update, others...). Args: type (:obj:`type`): The ``type`` of updates this handler should process, as @@ -50,6 +57,10 @@ class TypeHandler(Handler): ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be + ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can + be difficult to determine if :attr:`callback` is decorated - especially on python 2. """ From 5738f0028bf1ff02333612a118100a4470691d1b Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 19:42:56 +0200 Subject: [PATCH 04/32] Add Context to docs --- docs/source/telegram.ext.context.rst | 5 +++ docs/source/telegram.ext.rst | 1 + telegram/ext/context.py | 54 +++++++++++++++++++--------- 3 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 docs/source/telegram.ext.context.rst diff --git a/docs/source/telegram.ext.context.rst b/docs/source/telegram.ext.context.rst new file mode 100644 index 00000000000..9943be3cca6 --- /dev/null +++ b/docs/source/telegram.ext.context.rst @@ -0,0 +1,5 @@ +telegram.ext.Context +==================== + +.. autoclass:: telegram.ext.Context + :members: diff --git a/docs/source/telegram.ext.rst b/docs/source/telegram.ext.rst index d54e0542561..0d41eefb8d8 100644 --- a/docs/source/telegram.ext.rst +++ b/docs/source/telegram.ext.rst @@ -10,6 +10,7 @@ telegram.ext package telegram.ext.jobqueue telegram.ext.messagequeue telegram.ext.delayqueue + telegram.ext.context Handlers -------- diff --git a/telegram/ext/context.py b/telegram/ext/context.py index 3c4a64bb03e..fd252063905 100644 --- a/telegram/ext/context.py +++ b/telegram/ext/context.py @@ -20,33 +20,55 @@ class Context(object): """ + This object represents an incoming update from a telegram bot. + It operates like a supercharged :class:`telegram.Update`, in that it includes + data that the handler passed along. + To use it set :attr:`use_context` to ``True`` when creating your handlers, and use the + following signature for your callback functions ``def callbackname(context):``. + Note that setting :attr:`use_context` may not be required unless using old versions of + python or decorators on the callback. Attributes: - bot: - update: - chat_data: - user_data: - groups: - groupdict: - job_queue: - update_queue: - args: + bot (:class:`telegram.Bot`): The bot associated with this context. + update (:class:`telegram.Update`): The update that spawned this context. + chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same chat it will be the same ``dict``. + user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same user it will be the same ``dict``. + groups (:obj:`tuple`, optional): If the associated update originated from a + regex-supported handler, this will contain the ``re.match(pattern, data).groups()``. + groupdict (:obj:`dict`, optional): If the associated update originated from a + regex-supported handler, this will contain the ``re.match(pattern, data).groupdict()``. + job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the + :class:`telegram.ext.Updater` which can be used to schedule new jobs. + update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the + :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` + which contains new updates and can be used to insert updates. + args (List[:obj:`str`], optional): Arguments passed to a command if the associated update + originated from a :class:`telegram.ext.CommandHandler` or a + :class:`telegram.ext.StringCommandHandler`. It will contain a list of strings, + which is the text following the command split on single or consecutive whitespace + characters. message (:class:`telegram.Message`, optional): New incoming message of any kind - text, - photo, sticker, etc. + photo, sticker, etc. Extracted from :attr:`update`. edited_message (:class:`telegram.Message`, optional): New version of a message that is - known to the bot and was edited. + known to the bot and was edited. Extracted from :attr:`update`. channel_post (:class:`telegram.Message`, optional): New incoming channel post of any kind - - text, photo, sticker, etc. + - text, photo, sticker, etc. Extracted from :attr:`update`. edited_channel_post (:class:`telegram.Message`, optional): New version of a channel post - that is known to the bot and was edited. + that is known to the bot and was edited. Extracted from :attr:`update`. inline_query (:class:`telegram.InlineQuery`, optional): New incoming inline query. + Extracted from :attr:`update`. chosen_inline_result (:class:`telegram.ChosenInlineResult`, optional): The result of an - inline query that was chosen by a user and sent to their chat partner. + inline query that was chosen by a user and sent to their chat partner. Extracted + from :attr:`update`. callback_query (:class:`telegram.CallbackQuery`, optional): New incoming callback query. + Extracted from :attr:`update`. shipping_query (:class:`telegram.ShippingQuery`, optional): New incoming shipping query. - Only for invoices with flexible price. + Only for invoices with flexible price. Extracted from :attr:`update`. pre_checkout_query (:class:`telegram.PreCheckoutQuery`, optional): New incoming - pre-checkout query. Contains full information about checkout + pre-checkout query. Contains full information about checkout. Extracted from + :attr:`update`. """ def __init__(self, update, dispatcher): From 0580ae318bd34d8ac5547897f7824a2c150d53c1 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 21:14:00 +0200 Subject: [PATCH 05/32] Minor fixes to context handling --- telegram/ext/callbackqueryhandler.py | 6 ++--- telegram/ext/commandhandler.py | 5 ++-- telegram/ext/context.py | 35 +++++++++++++++++++--------- telegram/ext/inlinequeryhandler.py | 6 ++--- telegram/ext/regexhandler.py | 22 +++++++---------- telegram/ext/stringcommandhandler.py | 3 +-- telegram/ext/stringregexhandler.py | 6 ++--- 7 files changed, 42 insertions(+), 41 deletions(-) diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index 84bc19e5bf2..f307731d5b1 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -151,7 +151,5 @@ def collect_additional_context(self, context, update, dispatcher): if self.pattern: match = re.match(self.pattern, update.callback_query.data) - if self.pass_groups: - context.groups = match.groups() - if self.pass_groupdict: - context.groupdict = match.groupdict() + context.groups = match.groups() + context.groupdict = match.groupdict() diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 00c622a8e35..19f01f52656 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -176,6 +176,5 @@ def collect_optional_args(self, dispatcher, update=None): return optional_args def collect_additional_context(self, context, update, dispatcher): - if self.pass_args: - message = update.message or update.edited_message - context.args = message.text.split()[1:] + message = update.message or update.edited_message + context.args = message.text.split()[1:] diff --git a/telegram/ext/context.py b/telegram/ext/context.py index fd252063905..1c2549751fe 100644 --- a/telegram/ext/context.py +++ b/telegram/ext/context.py @@ -16,6 +16,7 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from telegram import Update class Context(object): @@ -74,9 +75,21 @@ class Context(object): def __init__(self, update, dispatcher): self.update = update self.bot = dispatcher.bot + self.chat_data = None self.user_data = None - if update is not None: + + self.message = None + self.edited_message = None + self.inline_query = None + self.chosen_inline_result = None + self.callback_query = None + self.shipping_query = None + self.pre_checkout_query = None + self.channel_post = None + self.edited_channel_post = None + + if update is not None and isinstance(update, Update): chat = update.effective_chat user = update.effective_user @@ -85,19 +98,19 @@ def __init__(self, update, dispatcher): if user: self.user_data = dispatcher.user_data[user.id] + self.message = self.update.message + self.edited_message = self.update.edited_message + self.inline_query = self.update.inline_query + self.chosen_inline_result = self.update.chosen_inline_result + self.callback_query = self.update.callback_query + self.shipping_query = self.update.shipping_query + self.pre_checkout_query = self.update.pre_checkout_query + self.channel_post = self.update.channel_post + self.edited_channel_post = self.update.edited_channel_post + self.job_queue = dispatcher.job_queue self.update_queue = dispatcher.update_queue - self.message = self.update.message - self.edited_message = self.update.edited_message - self.inline_query = self.update.inline_query - self.chosen_inline_result = self.update.chosen_inline_result - self.callback_query = self.update.callback_query - self.shipping_query = self.update.shipping_query - self.pre_checkout_query = self.update.pre_checkout_query - self.channel_post = self.update.channel_post - self.edited_channel_post = self.update.edited_channel_post - self.args = None self.groups = None self.groupdict = None diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index b86df45a446..45067ee4718 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -150,7 +150,5 @@ def collect_additional_context(self, context, update, dispatcher): if self.pattern: match = re.match(self.pattern, update.inline_query.query) - if self.pass_groups: - context.groups = match.groups() - if self.pass_groupdict: - context.groupdict = match.groupdict() + context.groups = match.groups() + context.groupdict = match.groupdict() diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 7710dad95cb..7504a9da8ce 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -132,7 +132,7 @@ def __init__(self, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, pass_chat_data=pass_chat_data, - use_context=None) + use_context=use_context) if isinstance(pattern, string_types): pattern = re.compile(pattern) @@ -167,20 +167,16 @@ def check_update(self, update): def collect_optional_args(self, dispatcher, update=None): optional_args = super(RegexHandler, self).collect_optional_args(dispatcher, update) - if self.pattern: - match = re.match(self.pattern, update.effective_message.text) + match = re.match(self.pattern, update.effective_message.text) - if self.pass_groups: - optional_args['groups'] = match.groups() - if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + if self.pass_groups: + optional_args['groups'] = match.groups() + if self.pass_groupdict: + optional_args['groupdict'] = match.groupdict() return optional_args def collect_additional_context(self, context, update, dispatcher): - if self.pattern: - match = re.match(self.pattern, update.effective_message.text) + match = re.match(self.pattern, update.effective_message.text) - if self.pass_groups: - context.groups = match.groups() - if self.pass_groupdict: - context.groupdict = match.groupdict() + context.groups = match.groups() + context.groupdict = match.groupdict() diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 2012ba2569f..2ec8cd02a81 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -108,5 +108,4 @@ def collect_optional_args(self, dispatcher, update=None): return optional_args def collect_additional_context(self, context, update, dispatcher): - if self.pass_args: - context.args = update.split()[1:] + context.args = update.split()[1:] diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index 8bdccb5bc2b..eca5b166730 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -128,7 +128,5 @@ def collect_additional_context(self, context, update, dispatcher): if self.pattern: match = re.match(self.pattern, update) - if self.pass_groups: - context.groups = match.groups() - if self.pass_groupdict: - context.groupdict = match.groupdict() + context.groups = match.groups() + context.groupdict = match.groupdict() From bad8f35f1641c1d0df784a0ccbbf85bbffa116fe Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 21:16:38 +0200 Subject: [PATCH 06/32] Add tests for context stuff --- tests/test_callbackqueryhandler.py | 52 ++++++++++++++++++++++++- tests/test_choseninlineresulthandler.py | 27 ++++++++++++- tests/test_commandhandler.py | 52 +++++++++++++++++++++++-- tests/test_inlinequeryhandler.py | 50 +++++++++++++++++++++++- tests/test_messagehandler.py | 51 +++++++++++++++++++++++- tests/test_precheckoutqueryhandler.py | 27 ++++++++++++- tests/test_regexhandler.py | 49 ++++++++++++++++++++++- tests/test_shippingqueryhandler.py | 27 ++++++++++++- tests/test_stringcommandhandler.py | 40 ++++++++++++++++++- tests/test_stringregexhandler.py | 45 ++++++++++++++++++++- tests/test_typehandler.py | 26 ++++++++++++- 11 files changed, 429 insertions(+), 17 deletions(-) diff --git a/tests/test_callbackqueryhandler.py b/tests/test_callbackqueryhandler.py index 97b342f3335..d24ef4ef3e4 100644 --- a/tests/test_callbackqueryhandler.py +++ b/tests/test_callbackqueryhandler.py @@ -16,11 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue + import pytest from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CallbackQueryHandler +from telegram.ext import CallbackQueryHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -47,7 +49,7 @@ def false_update(request): @pytest.fixture(scope='function') def callback_query(bot): - return Update(0, callback_query=CallbackQuery(2, None, None, data='test data')) + return Update(0, callback_query=CallbackQuery(2, User(1, '', False), None, data='test data')) class TestCallbackQueryHandler(object): @@ -80,6 +82,22 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' data'} + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + context.chat_data is None and + isinstance(context.callback_query, CallbackQuery)) + + def callback_context_pattern(self, context): + if context.groups: + self.test_flag = context.groups == ('t', ' data') + if context.groupdict: + self.test_flag = context.groupdict == {'begin': 't', 'end': ' data'} + def test_basic(self, dp, callback_query): handler = CallbackQueryHandler(self.callback_basic) dp.add_handler(handler) @@ -167,3 +185,33 @@ def test_pass_job_or_update_queue(self, dp, callback_query): def test_other_update_types(self, false_update): handler = CallbackQueryHandler(self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp, callback_query): + handler = CallbackQueryHandler(self.callback_context) + dp.add_handler(handler) + + dp.process_update(callback_query) + assert self.test_flag + + def test_not_context(self, dp, callback_query): + handler = CallbackQueryHandler(self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(callback_query) + assert not self.test_flag + + def test_context_pattern(self, dp, callback_query): + handler = CallbackQueryHandler(self.callback_context_pattern, + pattern=r'(?P.*)est(?P.*)') + dp.add_handler(handler) + + dp.process_update(callback_query) + assert self.test_flag + + dp.remove_handler(handler) + handler = CallbackQueryHandler(self.callback_context_pattern, + pattern=r'(t)est(.*)') + dp.add_handler(handler) + + dp.process_update(callback_query) + assert self.test_flag diff --git a/tests/test_choseninlineresulthandler.py b/tests/test_choseninlineresulthandler.py index b0ca6b34394..a2993e00817 100644 --- a/tests/test_choseninlineresulthandler.py +++ b/tests/test_choseninlineresulthandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import ChosenInlineResultHandler +from telegram.ext import ChosenInlineResultHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -78,6 +79,16 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + context.chat_data is None and + isinstance(context.chosen_inline_result, ChosenInlineResult)) + def test_basic(self, dp, chosen_inline_result): handler = ChosenInlineResultHandler(self.callback_basic) dp.add_handler(handler) @@ -137,3 +148,17 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): def test_other_update_types(self, false_update): handler = ChosenInlineResultHandler(self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp, chosen_inline_result): + handler = ChosenInlineResultHandler(self.callback_context) + dp.add_handler(handler) + + dp.process_update(chosen_inline_result) + assert self.test_flag + + def test_not_context(self, dp, chosen_inline_result): + handler = ChosenInlineResultHandler(self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(chosen_inline_result) + assert not self.test_flag diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index 7b06b7e1c0a..84ef564804c 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CommandHandler, Filters, BaseFilter +from telegram.ext import CommandHandler, Filters, BaseFilter, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='test') @@ -48,7 +49,7 @@ def false_update(request): @pytest.fixture(scope='function') def message(bot): - return Message(1, None, None, None, bot=bot) + return Message(1, User(1, '', False), None, Chat(1, ''), bot=bot) class TestCommandHandler(object): @@ -83,6 +84,19 @@ def ch_callback_args(self, bot, update, args): else: self.test_flag = args == ['one', 'two'] + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + isinstance(context.chat_data, dict) and + isinstance(context.message, Message)) + + def callback_context_args(self, context): + self.test_flag = context.args == ['one', 'two'] + def test_basic(self, dp, message): handler = CommandHandler('test', self.callback_basic) dp.add_handler(handler) @@ -148,8 +162,6 @@ def test_pass_args(self, dp, message): message.text = '/test' dp.process_update(Update(0, message=message)) - import time - time.sleep(.1) assert self.test_flag self.test_flag = False @@ -267,3 +279,35 @@ def filter(self, message): handler.check_update(Update(0, message=message)) assert not test_filter.tested + + def test_context(self, dp, message): + handler = CommandHandler('test', self.callback_context) + dp.add_handler(handler) + + message.text = '/test' + assert handler.check_update(Update(0, message)) + dp.process_update(Update(0, message)) + assert self.test_flag + + def test_not_context(self, dp, message): + handler = CommandHandler('test', self.callback_context, use_context=False) + dp.add_handler(handler) + + message.text = '/test' + assert handler.check_update(Update(0, message)) + dp.process_update(Update(0, message)) + assert not self.test_flag + + def test_context_args(self, dp, message): + handler = CommandHandler('test', self.callback_context_args) + dp.add_handler(handler) + + message.text = '/test' + assert handler.check_update(Update(0, message)) + dp.process_update(Update(0, message)) + assert not self.test_flag + + message.text = '/test one two' + assert handler.check_update(Update(0, message)) + dp.process_update(Update(0, message)) + assert self.test_flag diff --git a/tests/test_inlinequeryhandler.py b/tests/test_inlinequeryhandler.py index 1ff82889160..ec99c0ac4db 100644 --- a/tests/test_inlinequeryhandler.py +++ b/tests/test_inlinequeryhandler.py @@ -16,11 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue + import pytest from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery, Location) -from telegram.ext import InlineQueryHandler +from telegram.ext import InlineQueryHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -84,6 +86,22 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' query'} + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + context.chat_data is None and + isinstance(context.inline_query, InlineQuery)) + + def callback_context_pattern(self, context): + if context.groups: + self.test_flag = context.groups == ('t', ' query') + if context.groupdict: + self.test_flag = context.groupdict == {'begin': 't', 'end': ' query'} + def test_basic(self, dp, inline_query): handler = InlineQueryHandler(self.callback_basic) dp.add_handler(handler) @@ -171,3 +189,33 @@ def test_pass_job_or_update_queue(self, dp, inline_query): def test_other_update_types(self, false_update): handler = InlineQueryHandler(self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp, inline_query): + handler = InlineQueryHandler(self.callback_context) + dp.add_handler(handler) + + dp.process_update(inline_query) + assert self.test_flag + + def test_not_context(self, dp, inline_query): + handler = InlineQueryHandler(self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(inline_query) + assert not self.test_flag + + def test_context_pattern(self, dp, inline_query): + handler = InlineQueryHandler(self.callback_context_pattern, + pattern=r'(?P.*)est(?P.*)') + dp.add_handler(handler) + + dp.process_update(inline_query) + assert self.test_flag + + dp.remove_handler(handler) + handler = InlineQueryHandler(self.callback_context_pattern, + pattern=r'(t)est(.*)') + dp.add_handler(handler) + + dp.process_update(inline_query) + assert self.test_flag diff --git a/tests/test_messagehandler.py b/tests/test_messagehandler.py index 8ccac3335d8..e4dd522a7a2 100644 --- a/tests/test_messagehandler.py +++ b/tests/test_messagehandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import Filters, MessageHandler +from telegram.ext import Filters, MessageHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -45,7 +46,7 @@ def false_update(request): @pytest.fixture(scope='class') def message(bot): - return Message(1, None, None, None, bot=bot) + return Message(1, User(1, '', False), None, Chat(1, ''), bot=bot) class TestMessageHandler(object): @@ -72,6 +73,25 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) + def callback_context(self, context): + self.test_flag = ( + isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.chat_data, dict) and + ( + (isinstance(context.user_data, dict) and + (isinstance(context.message, Message) or + isinstance(context.edited_message, Message))) + or + (context.user_data is None and + (isinstance(context.channel_post, Message) or + isinstance(context.edited_channel_post, Message))) + ) + ) + def test_basic(self, dp, message): handler = MessageHandler(None, self.callback_basic) dp.add_handler(handler) @@ -182,3 +202,30 @@ def test_pass_job_or_update_queue(self, dp, message): def test_other_update_types(self, false_update): handler = MessageHandler(None, self.callback_basic, edited_updates=True) assert not handler.check_update(false_update) + + def test_context(self, dp, message): + handler = MessageHandler(None, self.callback_context, edited_updates=True, + channel_post_updates=True) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert self.test_flag + + self.test_flag = False + dp.process_update(Update(0, edited_message=message)) + assert self.test_flag + + self.test_flag = False + dp.process_update(Update(0, channel_post=message)) + assert self.test_flag + + self.test_flag = False + dp.process_update(Update(0, edited_channel_post=message)) + assert self.test_flag + + def test_not_context(self, dp, message): + handler = MessageHandler(None, self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert not self.test_flag diff --git a/tests/test_precheckoutqueryhandler.py b/tests/test_precheckoutqueryhandler.py index 01f4aec89b3..061492ce733 100644 --- a/tests/test_precheckoutqueryhandler.py +++ b/tests/test_precheckoutqueryhandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import PreCheckoutQueryHandler +from telegram.ext import PreCheckoutQueryHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -78,6 +79,16 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + context.chat_data is None and + isinstance(context.pre_checkout_query, PreCheckoutQuery)) + def test_basic(self, dp, pre_checkout_query): handler = PreCheckoutQueryHandler(self.callback_basic) dp.add_handler(handler) @@ -137,3 +148,17 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): def test_other_update_types(self, false_update): handler = PreCheckoutQueryHandler(self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp, pre_checkout_query): + handler = PreCheckoutQueryHandler(self.callback_context) + dp.add_handler(handler) + + dp.process_update(pre_checkout_query) + assert self.test_flag + + def test_not_context(self, dp, pre_checkout_query): + handler = PreCheckoutQueryHandler(self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(pre_checkout_query) + assert not self.test_flag diff --git a/tests/test_regexhandler.py b/tests/test_regexhandler.py index 025a06b774f..f14e8c8c48e 100644 --- a/tests/test_regexhandler.py +++ b/tests/test_regexhandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import RegexHandler +from telegram.ext import RegexHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -45,7 +46,7 @@ def false_update(request): @pytest.fixture(scope='class') def message(bot): - return Message(1, None, None, None, text='test message', bot=bot) + return Message(1, User(1, '', False), None, Chat(1, ''), text='test message', bot=bot) class TestRegexHandler(object): @@ -78,6 +79,22 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' message'} + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + isinstance(context.chat_data, dict) and + isinstance(context.message, Message)) + + def callback_context_pattern(self, context): + if context.groups: + self.test_flag = context.groups == ('t', ' message') + if context.groupdict: + self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} + def test_basic(self, dp, message): handler = RegexHandler('.*', self.callback_basic) dp.add_handler(handler) @@ -204,3 +221,31 @@ def test_pass_job_or_update_queue(self, dp, message): def test_other_update_types(self, false_update): handler = RegexHandler('.*', self.callback_basic, edited_updates=True) assert not handler.check_update(false_update) + + def test_context(self, dp, message): + handler = RegexHandler(r'(t)est(.*)', self.callback_context) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert self.test_flag + + def test_not_context(self, dp, message): + handler = RegexHandler(r'(t)est(.*)', self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert not self.test_flag + + def test_context_pattern(self, dp, message): + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert self.test_flag + + dp.remove_handler(handler) + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + dp.add_handler(handler) + + dp.process_update(Update(0, message=message)) + assert self.test_flag diff --git a/tests/test_shippingqueryhandler.py b/tests/test_shippingqueryhandler.py index d164dee11fd..5d5ca042115 100644 --- a/tests/test_shippingqueryhandler.py +++ b/tests/test_shippingqueryhandler.py @@ -16,12 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery, ShippingAddress) -from telegram.ext import ShippingQueryHandler +from telegram.ext import ShippingQueryHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -79,6 +80,16 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, Update) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.user_data, dict) and + context.chat_data is None and + isinstance(context.shipping_query, ShippingQuery)) + def test_basic(self, dp, shiping_query): handler = ShippingQueryHandler(self.callback_basic) dp.add_handler(handler) @@ -138,3 +149,17 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): def test_other_update_types(self, false_update): handler = ShippingQueryHandler(self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp, shiping_query): + handler = ShippingQueryHandler(self.callback_context) + dp.add_handler(handler) + + dp.process_update(shiping_query) + assert self.test_flag + + def test_not_context(self, dp, shiping_query): + handler = ShippingQueryHandler(self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update(shiping_query) + assert not self.test_flag diff --git a/tests/test_stringcommandhandler.py b/tests/test_stringcommandhandler.py index 382471ab475..07d4d096adb 100644 --- a/tests/test_stringcommandhandler.py +++ b/tests/test_stringcommandhandler.py @@ -16,11 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue + import pytest from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringCommandHandler +from telegram.ext import StringCommandHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -71,6 +73,18 @@ def sch_callback_args(self, bot, update, args): else: self.test_flag = args == ['one', 'two'] + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, str) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + context.user_data is None and + context.chat_data is None) + + def callback_context_args(self, context): + self.test_flag = context.args == ['one', 'two'] + def test_basic(self, dp): handler = StringCommandHandler('test', self.callback_basic) dp.add_handler(handler) @@ -121,3 +135,27 @@ def test_pass_job_or_update_queue(self, dp): def test_other_update_types(self, false_update): handler = StringCommandHandler('test', self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp): + handler = StringCommandHandler('test', self.callback_context) + dp.add_handler(handler) + + dp.process_update('/test') + assert self.test_flag + + def test_not_context(self, dp): + handler = StringCommandHandler('test', self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update('/test') + assert not self.test_flag + + def test_context_args(self, dp): + handler = StringCommandHandler('test', self.callback_context_args) + dp.add_handler(handler) + + dp.process_update('/test') + assert not self.test_flag + + dp.process_update('/test one two') + assert self.test_flag diff --git a/tests/test_stringregexhandler.py b/tests/test_stringregexhandler.py index e5ae8ffdc16..84dcf46fb87 100644 --- a/tests/test_stringregexhandler.py +++ b/tests/test_stringregexhandler.py @@ -16,11 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +from queue import Queue + import pytest from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringRegexHandler +from telegram.ext import StringRegexHandler, Context, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -71,6 +73,19 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' message'} + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, str) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue)) + + def callback_context_pattern(self, context): + if context.groups: + self.test_flag = context.groups == ('t', ' message') + if context.groupdict: + self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} + def test_basic(self, dp): handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic) dp.add_handler(handler) @@ -125,3 +140,31 @@ def test_pass_job_or_update_queue(self, dp): def test_other_update_types(self, false_update): handler = StringRegexHandler('test', self.callback_basic) assert not handler.check_update(false_update) + + def test_context(self, dp): + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context) + dp.add_handler(handler) + + dp.process_update('test message') + assert self.test_flag + + def test_not_context(self, dp): + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update('test message') + assert not self.test_flag + + def test_context_pattern(self, dp): + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + dp.add_handler(handler) + + dp.process_update('test message') + assert self.test_flag + + dp.remove_handler(handler) + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + dp.add_handler(handler) + + dp.process_update('test message') + assert self.test_flag diff --git a/tests/test_typehandler.py b/tests/test_typehandler.py index 6dcc982d339..110a3d5a260 100644 --- a/tests/test_typehandler.py +++ b/tests/test_typehandler.py @@ -17,11 +17,12 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. from collections import OrderedDict +from queue import Queue import pytest from telegram import Bot -from telegram.ext import TypeHandler +from telegram.ext import TypeHandler, Context, JobQueue class TestTypeHandler(object): @@ -42,6 +43,15 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) + def callback_context(self, context): + self.test_flag = (isinstance(context, Context) and + isinstance(context.bot, Bot) and + isinstance(context.update, dict) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + context.user_data is None and + context.chat_data is None) + def test_basic(self, dp): handler = TypeHandler(dict, self.callback_basic) dp.add_handler(handler) @@ -80,3 +90,17 @@ def test_pass_job_or_update_queue(self, dp): self.test_flag = False dp.process_update({'a': 1, 'b': 2}) assert self.test_flag + + def test_context(self, dp): + handler = TypeHandler(dict, self.callback_context) + dp.add_handler(handler) + + dp.process_update({'a': 1, 'b': 2}) + assert self.test_flag + + def test_not_context(self, dp): + handler = TypeHandler(dict, self.callback_context, use_context=False) + dp.add_handler(handler) + + dp.process_update({'a': 1, 'b': 2}) + assert not self.test_flag From 7e2fb8db6be738d383842f0b43b0a36c95cba465 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 21:50:17 +0200 Subject: [PATCH 07/32] Allow the signature check to work on py<3.5 with methods --- telegram/ext/handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index c666e28cfca..088c3d32b81 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -99,10 +99,10 @@ def __init__(self, self.use_context = len(parameters) == 1 elif has_full_argspec: argspec = inspect.getfullargspec(callback) - self.use_context = len(argspec.args) == 1 + self.use_context = len(argspec.args) == 2 if inspect.ismethod(callback) else 1 else: argspec = inspect.getargspec(callback) - self.use_context = len(argspec.args) == 1 + self.use_context = len(argspec.args) == 2 if inspect.ismethod(callback) else 1 def check_update(self, update): """ From d133dd4c93fbe0a2c95fe9d3e8763d6e7ccb92d7 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 3 May 2018 22:13:23 +0200 Subject: [PATCH 08/32] Fix order of operations --- telegram/ext/handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 088c3d32b81..a5480fa5000 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -99,10 +99,10 @@ def __init__(self, self.use_context = len(parameters) == 1 elif has_full_argspec: argspec = inspect.getfullargspec(callback) - self.use_context = len(argspec.args) == 2 if inspect.ismethod(callback) else 1 + self.use_context = len(argspec.args) == (2 if inspect.ismethod(callback) else 1) else: argspec = inspect.getargspec(callback) - self.use_context = len(argspec.args) == 2 if inspect.ismethod(callback) else 1 + self.use_context = len(argspec.args) == (2 if inspect.ismethod(callback) else 1) def check_update(self, update): """ From 5bfaca0baf2157925bb904aee0e700b504995cb4 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Fri, 4 May 2018 14:35:58 +0200 Subject: [PATCH 09/32] Address most issues raised in CR --- CHANGES.rst | 9 ++ docs/source/telegram.ext.context.rst | 5 - docs/source/telegram.ext.handlercontext.rst | 6 + docs/source/telegram.ext.rst | 2 +- telegram/ext/__init__.py | 5 +- telegram/ext/callbackqueryhandler.py | 39 +++---- telegram/ext/choseninlineresulthandler.py | 31 ++---- telegram/ext/commandhandler.py | 31 +++--- telegram/ext/context.py | 116 ------------------- telegram/ext/conversationhandler.py | 54 +++++---- telegram/ext/dispatcher.py | 6 +- telegram/ext/handler.py | 117 ++++++++++++++------ telegram/ext/inlinequeryhandler.py | 38 +++---- telegram/ext/messagehandler.py | 25 ++--- telegram/ext/precheckoutqueryhandler.py | 29 ++--- telegram/ext/regexhandler.py | 41 ++++--- telegram/ext/shippingqueryhandler.py | 29 ++--- telegram/ext/stringcommandhandler.py | 20 ++-- telegram/ext/stringregexhandler.py | 36 +++--- telegram/ext/typehandler.py | 10 +- tests/test_callbackqueryhandler.py | 58 +++++----- tests/test_choseninlineresulthandler.py | 46 ++++---- tests/test_commandhandler.py | 70 ++++++------ tests/test_conversationhandler.py | 42 ++++--- tests/test_inlinequeryhandler.py | 54 ++++----- tests/test_messagehandler.py | 72 ++++++------ tests/test_precheckoutqueryhandler.py | 44 ++++---- tests/test_regexhandler.py | 62 ++++++----- tests/test_shippingqueryhandler.py | 44 ++++---- tests/test_stringcommandhandler.py | 40 +++---- tests/test_stringregexhandler.py | 47 ++++---- tests/test_typehandler.py | 31 +++--- 32 files changed, 590 insertions(+), 669 deletions(-) delete mode 100644 docs/source/telegram.ext.context.rst create mode 100644 docs/source/telegram.ext.handlercontext.rst delete mode 100644 telegram/ext/context.py diff --git a/CHANGES.rst b/CHANGES.rst index bc39ae7af2c..d570584898e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,15 @@ ======= Changes ======= +**2018-??-??** +*Released 11.0.0* + +Handler overhaul: + +- Use of `pass_` in handlers is deprecated. +- Instead use `use_context=True` and change callback from (bot, update, others...) to (update, context) See https://git.io/vpVe8 for help. +- Handlers should be faster due to deduped logic. For those with their own handlers subclass telegram.ext.Handler, this is backwards incompatible. + **2018-04-17** *Released 10.0.2* diff --git a/docs/source/telegram.ext.context.rst b/docs/source/telegram.ext.context.rst deleted file mode 100644 index 9943be3cca6..00000000000 --- a/docs/source/telegram.ext.context.rst +++ /dev/null @@ -1,5 +0,0 @@ -telegram.ext.Context -==================== - -.. autoclass:: telegram.ext.Context - :members: diff --git a/docs/source/telegram.ext.handlercontext.rst b/docs/source/telegram.ext.handlercontext.rst new file mode 100644 index 00000000000..33daee780be --- /dev/null +++ b/docs/source/telegram.ext.handlercontext.rst @@ -0,0 +1,6 @@ +telegram.ext.HandlerContext +=========================== + +.. autoclass:: telegram.ext.HandlerContext + :members: + :undoc-members: diff --git a/docs/source/telegram.ext.rst b/docs/source/telegram.ext.rst index 0d41eefb8d8..1e1b0acad4f 100644 --- a/docs/source/telegram.ext.rst +++ b/docs/source/telegram.ext.rst @@ -10,7 +10,7 @@ telegram.ext package telegram.ext.jobqueue telegram.ext.messagequeue telegram.ext.delayqueue - telegram.ext.context + telegram.ext.handlercontext Handlers -------- diff --git a/telegram/ext/__init__.py b/telegram/ext/__init__.py index 63fd72cb0b8..87dbf6069a7 100644 --- a/telegram/ext/__init__.py +++ b/telegram/ext/__init__.py @@ -18,14 +18,13 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """Extensions over the Telegram Bot API to facilitate bot making""" -from .context import Context from .dispatcher import Dispatcher, DispatcherHandlerStop, run_async from .jobqueue import JobQueue, Job from .updater import Updater from .callbackqueryhandler import CallbackQueryHandler from .choseninlineresulthandler import ChosenInlineResultHandler from .commandhandler import CommandHandler -from .handler import Handler +from .handler import Handler, HandlerContext from .inlinequeryhandler import InlineQueryHandler from .messagehandler import MessageHandler from .filters import BaseFilter, Filters @@ -44,4 +43,4 @@ 'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler', 'StringRegexHandler', 'TypeHandler', 'ConversationHandler', 'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue', - 'DispatcherHandlerStop', 'run_async', 'Context') + 'DispatcherHandlerStop', 'run_async', 'HandlerContext') diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index f307731d5b1..af8ca3bed35 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -55,11 +55,8 @@ class CallbackQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -69,27 +66,32 @@ class CallbackQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pattern (:obj:`str` | `Pattern`, optional): Regex pattern. If not ``None``, ``re.match`` is used on :attr:`telegram.CallbackQuery.data` to determine if an update should be handled by this handler. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ @@ -132,24 +134,23 @@ def check_update(self, update): if self.pattern: if update.callback_query.data: match = re.match(self.pattern, update.callback_query.data) - return bool(match) + if match: + return match else: return True - def collect_optional_args(self, dispatcher, update=None): - optional_args = super(CallbackQueryHandler, self).collect_optional_args(dispatcher, update) + def collect_optional_args(self, dispatcher, update=None, check_result=None): + optional_args = super(CallbackQueryHandler, self).collect_optional_args(dispatcher, + update, + check_result) if self.pattern: - match = re.match(self.pattern, update.callback_query.data) - if self.pass_groups: - optional_args['groups'] = match.groups() + optional_args['groups'] = check_result.groups() if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + optional_args['groupdict'] = check_result.groupdict() return optional_args - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - match = re.match(self.pattern, update.callback_query.data) - - context.groups = match.groups() - context.groupdict = match.groupdict() + context.groups = check_result.groups() + context.groupdict = check_result.groupdict() diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index 39fdf73fcf1..a4bf79bef83 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -18,8 +18,8 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the ChosenInlineResultHandler class.""" -from .handler import Handler from telegram import Update +from .handler import Handler class ChosenInlineResultHandler(Handler): @@ -43,11 +43,8 @@ class ChosenInlineResultHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -57,36 +54,24 @@ class ChosenInlineResultHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ - def __init__(self, - callback, - pass_update_queue=False, - pass_job_queue=False, - pass_user_data=False, - pass_chat_data=False, - use_context=None): - super(ChosenInlineResultHandler, self).__init__( - callback, - pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) - def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 19f01f52656..542b1eadf1d 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -57,11 +57,8 @@ class CommandHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: command (:obj:`str` | List[:obj:`str`]): The command or list of commands this handler @@ -79,22 +76,26 @@ class CommandHandler(Handler): arguments passed to the command as a keyword argument called ``args``. It will contain a list of strings, which is the text following the command split on single or consecutive whitespace characters. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ @@ -155,26 +156,22 @@ def check_update(self, update): if not (command[0].lower() in self.command and command[1].lower() == message.bot.username.lower()): - return False + return None if self.filters is None: - res = True + return True elif isinstance(self.filters, list): - res = any(func(message) for func in self.filters) + return any(func(message) for func in self.filters) else: - res = self.filters(message) - - return res - - return False + return self.filters(message) - def collect_optional_args(self, dispatcher, update=None): + def collect_optional_args(self, dispatcher, update=None, check_result=None): optional_args = super(CommandHandler, self).collect_optional_args(dispatcher, update) if self.pass_args: message = update.message or update.edited_message optional_args['args'] = message.text.split()[1:] return optional_args - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): message = update.message or update.edited_message context.args = message.text.split()[1:] diff --git a/telegram/ext/context.py b/telegram/ext/context.py deleted file mode 100644 index 1c2549751fe..00000000000 --- a/telegram/ext/context.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# -# A library that provides a Python interface to the Telegram Bot API -# Copyright (C) 2015-2018 -# Leandro Toledo de Souza -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser Public License for more details. -# -# You should have received a copy of the GNU Lesser Public License -# along with this program. If not, see [http://www.gnu.org/licenses/]. -from telegram import Update - - -class Context(object): - """ - This object represents an incoming update from a telegram bot. - It operates like a supercharged :class:`telegram.Update`, in that it includes - data that the handler passed along. - To use it set :attr:`use_context` to ``True`` when creating your handlers, and use the - following signature for your callback functions ``def callbackname(context):``. - Note that setting :attr:`use_context` may not be required unless using old versions of - python or decorators on the callback. - - Attributes: - bot (:class:`telegram.Bot`): The bot associated with this context. - update (:class:`telegram.Update`): The update that spawned this context. - chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each - update from the same chat it will be the same ``dict``. - user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each - update from the same user it will be the same ``dict``. - groups (:obj:`tuple`, optional): If the associated update originated from a - regex-supported handler, this will contain the ``re.match(pattern, data).groups()``. - groupdict (:obj:`dict`, optional): If the associated update originated from a - regex-supported handler, this will contain the ``re.match(pattern, data).groupdict()``. - job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the - :class:`telegram.ext.Updater` which can be used to schedule new jobs. - update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the - :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` - which contains new updates and can be used to insert updates. - args (List[:obj:`str`], optional): Arguments passed to a command if the associated update - originated from a :class:`telegram.ext.CommandHandler` or a - :class:`telegram.ext.StringCommandHandler`. It will contain a list of strings, - which is the text following the command split on single or consecutive whitespace - characters. - message (:class:`telegram.Message`, optional): New incoming message of any kind - text, - photo, sticker, etc. Extracted from :attr:`update`. - edited_message (:class:`telegram.Message`, optional): New version of a message that is - known to the bot and was edited. Extracted from :attr:`update`. - channel_post (:class:`telegram.Message`, optional): New incoming channel post of any kind - - text, photo, sticker, etc. Extracted from :attr:`update`. - edited_channel_post (:class:`telegram.Message`, optional): New version of a channel post - that is known to the bot and was edited. Extracted from :attr:`update`. - inline_query (:class:`telegram.InlineQuery`, optional): New incoming inline query. - Extracted from :attr:`update`. - chosen_inline_result (:class:`telegram.ChosenInlineResult`, optional): The result of an - inline query that was chosen by a user and sent to their chat partner. Extracted - from :attr:`update`. - callback_query (:class:`telegram.CallbackQuery`, optional): New incoming callback query. - Extracted from :attr:`update`. - shipping_query (:class:`telegram.ShippingQuery`, optional): New incoming shipping query. - Only for invoices with flexible price. Extracted from :attr:`update`. - pre_checkout_query (:class:`telegram.PreCheckoutQuery`, optional): New incoming - pre-checkout query. Contains full information about checkout. Extracted from - :attr:`update`. - """ - - def __init__(self, update, dispatcher): - self.update = update - self.bot = dispatcher.bot - - self.chat_data = None - self.user_data = None - - self.message = None - self.edited_message = None - self.inline_query = None - self.chosen_inline_result = None - self.callback_query = None - self.shipping_query = None - self.pre_checkout_query = None - self.channel_post = None - self.edited_channel_post = None - - if update is not None and isinstance(update, Update): - chat = update.effective_chat - user = update.effective_user - - if chat: - self.chat_data = dispatcher.chat_data[chat.id] - if user: - self.user_data = dispatcher.user_data[user.id] - - self.message = self.update.message - self.edited_message = self.update.edited_message - self.inline_query = self.update.inline_query - self.chosen_inline_result = self.update.chosen_inline_result - self.callback_query = self.update.callback_query - self.shipping_query = self.update.shipping_query - self.pre_checkout_query = self.update.pre_checkout_query - self.channel_post = self.update.channel_post - self.edited_channel_post = self.update.edited_channel_post - - self.job_queue = dispatcher.job_queue - self.update_queue = dispatcher.update_queue - - self.args = None - self.groups = None - self.groupdict = None diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py index 0cc6633f87f..357423cbd15 100644 --- a/telegram/ext/conversationhandler.py +++ b/telegram/ext/conversationhandler.py @@ -147,8 +147,6 @@ def __init__(self, self.timeout_jobs = dict() self.conversations = dict() - self.current_conversation = None - self.current_handler = None self.logger = logging.getLogger(__name__) @@ -217,10 +215,10 @@ def check_update(self, update): # Ignore messages in channels if (not isinstance(update, Update) or update.channel_post or - self.per_chat and not update.effective_chat or - self.per_message and not update.callback_query or - update.callback_query and self.per_chat and not update.callback_query.message): - return False + self.per_chat and not update.effective_chat or + self.per_message and not update.callback_query or + update.callback_query and self.per_chat and not update.callback_query.message): + return None key = self._get_key(update) state = self.conversations.get(key) @@ -244,15 +242,13 @@ def check_update(self, update): else: for candidate in (self.timed_out_behavior or []): - if candidate.check_update(update): + check = candidate.check_update(update) + if check is not None and check is not False: # Save the current user and the selected handler for handle_update - self.current_conversation = key - self.current_handler = candidate - - return True + return key, candidate, check else: - return False + return None self.logger.debug('selecting conversation %s with state %s' % (str(key), str(state))) @@ -261,59 +257,61 @@ def check_update(self, update): # Search entry points for a match if state is None or self.allow_reentry: for entry_point in self.entry_points: - if entry_point.check_update(update): + check = entry_point.check_update(update) + if check is not None and check is not False: handler = entry_point break else: if state is None: - return False + return None # Get the handler list for current state, if we didn't find one yet and we're still here if state is not None and not handler: handlers = self.states.get(state) for candidate in (handlers or []): - if candidate.check_update(update): + check = candidate.check_update(update) + if check is not None and check is not False: handler = candidate break # Find a fallback handler if all other handlers fail else: for fallback in self.fallbacks: - if fallback.check_update(update): + check = fallback.check_update(update) + if check is not None and check is not False: handler = fallback break else: - return False - - # Save the current user and the selected handler for handle_update - self.current_conversation = key - self.current_handler = handler + return None - return True + return key, handler, check - def handle_update(self, update, dispatcher): + def handle_update(self, update, dispatcher, check_result): """Send the update to the callback for the current state and Handler Args: + check_result: The result from check_update. For this handler it's a tuple of key, + handler, and the handler's check result. update (:class:`telegram.Update`): Incoming telegram update. dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. """ - new_state = self.current_handler.handle_update(update, dispatcher) - timeout_job = self.timeout_jobs.pop(self.current_conversation, None) + new_state = check_result[1].handle_update(update, dispatcher, check_result[2]) + current_conversation = check_result[0] + timeout_job = self.timeout_jobs.pop(current_conversation, None) if timeout_job is not None: timeout_job.schedule_removal() if self.conversation_timeout and new_state != self.END: - self.timeout_jobs[self.current_conversation] = dispatcher.job_queue.run_once( + self.timeout_jobs[current_conversation] = dispatcher.job_queue.run_once( self._trigger_timeout, self.conversation_timeout, - context=self.current_conversation + context=current_conversation ) - self.update_state(new_state, self.current_conversation) + self.update_state(new_state, current_conversation) def update_state(self, new_state, key): if new_state == self.END: diff --git a/telegram/ext/dispatcher.py b/telegram/ext/dispatcher.py index 7756770b7d3..945c6ac8102 100644 --- a/telegram/ext/dispatcher.py +++ b/telegram/ext/dispatcher.py @@ -275,8 +275,10 @@ def process_update(self, update): for group in self.groups: try: - for handler in (x for x in self.handlers[group] if x.check_update(update)): - handler.handle_update(update, self) + for handler in self.handlers[group]: + check = handler.check_update(update) + if check is not None and check is not False: + handler.handle_update(update, self, check) break # Stop processing with any other handler. diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index a5480fa5000..a965e45485a 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -17,13 +17,10 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the base class for handlers as used by the Dispatcher.""" -import inspect -import sys +import warnings -from telegram.ext import Context - -has_follow_wrapped = sys.version_info >= (3, 5) -has_full_argspec = sys.version_info[0] == 3 +from telegram import Update +from telegram.utils.deprecate import TelegramDeprecationWarning class Handler(object): @@ -47,11 +44,8 @@ class Handler(object): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -61,18 +55,21 @@ class Handler(object): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ @@ -91,18 +88,15 @@ def __init__(self, self.use_context = use_context if use_context is None: - if has_follow_wrapped: - sig = inspect.signature(callback, follow_wrapped=True) - parameters = [p for p in sig.parameters.values() if p.kind == - inspect.Parameter.POSITIONAL_OR_KEYWORD or - p.kind == inspect.Parameter.POSITIONAL_ONLY] - self.use_context = len(parameters) == 1 - elif has_full_argspec: - argspec = inspect.getfullargspec(callback) - self.use_context = len(argspec.args) == (2 if inspect.ismethod(callback) else 1) - else: - argspec = inspect.getargspec(callback) - self.use_context = len(argspec.args) == (2 if inspect.ismethod(callback) else 1) + warnings.warn('You are currently not using context based handlers. This is being ' + 'deprecated, and will soon not be possible. Please change your ' + 'callback function signatures from (bot, update, others...) to (' + 'update, context), and create your handlers using use_context=True ' + 'instead of setting any pass_ parameters. You can set ' + 'use_context=False to turn this warning off. Please see ' + 'https://git.io/vpVe8 for more info.', + TelegramDeprecationWarning, + stacklevel=3) def check_update(self, update): """ @@ -118,7 +112,7 @@ def check_update(self, update): """ raise NotImplementedError - def handle_update(self, update, dispatcher): + def handle_update(self, update, dispatcher, check_result): """ This method is called if it was determined that an update should indeed be handled by this instance. Calls ``self.callback(dispatcher.bot, update)``, @@ -127,35 +121,40 @@ def handle_update(self, update, dispatcher): Note that it can be overridden if needed by the subclassing handler. Args: + check_result: The result from check_update update (:obj:`str` | :class:`telegram.Update`): The update to be handled. dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher to collect optional args. """ if self.use_context: - context = Context(update, dispatcher) - self.collect_additional_context(context, update, dispatcher) - return self.callback(context) + context = HandlerContext(update, dispatcher) + self.collect_additional_context(context, update, dispatcher, check_result) + return self.callback(update, context) else: - optional_args = self.collect_optional_args(dispatcher, update) + optional_args = self.collect_optional_args(dispatcher, update, check_result) return self.callback(dispatcher.bot, update, **optional_args) - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): """Prepares additional arguments for the context. Override if handler needs. Args: - context (:class:`telegram.ext.Context`): The context. + check_result: The result from check_update + context (:class:`telegram.ext.HandlerContext`): The context. dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. update (:class:`telegram.Update`): The update to gather chat/user id from. """ pass - def collect_optional_args(self, dispatcher, update=None): + def collect_optional_args(self, dispatcher, update=None, check_result=None): """Prepares the optional arguments. If the handler has additional optional args, it should subclass this method, but remember to call this super method. + Usage of this method is being replaced by new context aware handlers. Please see + https://git.io/vpVe8 for more info. Args: + check_result: The result from check_update dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. update (:class:`telegram.Update`): The update to gather chat/user id from. """ @@ -176,3 +175,55 @@ def collect_optional_args(self, dispatcher, update=None): optional_args['chat_data'] = dispatcher.chat_data[chat.id if chat else None] return optional_args + + +class HandlerContext(object): + """ + This object represents additional data passed along with an update from telegram. + To use it set :attr:`use_context` to ``True`` when creating your handlers, and use the + following signature for your callback functions ``def callbackname(update, context):``. + + Attributes: + bot (:class:`telegram.Bot`): The bot associated with this context. + chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same chat it will be the same ``dict``. + user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same user it will be the same ``dict``. + groups (:obj:`tuple`, optional): If the associated update originated from a + regex-supported handler, this will contain the ``re.match(pattern, data).groups()``. + groupdict (:obj:`dict`, optional): If the associated update originated from a + regex-supported handler, this will contain the ``re.match(pattern, data).groupdict()``. + job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the + :class:`telegram.ext.Updater` which can be used to schedule new jobs. + update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the + :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` + which contains new updates and can be used to insert updates. + args (List[:obj:`str`], optional): Arguments passed to a command if the associated update + originated from a :class:`telegram.ext.CommandHandler` or a + :class:`telegram.ext.StringCommandHandler`. It will contain a list of strings, + which is the text following the command split on single or consecutive whitespace + characters. + """ + + def __init__(self, update, dispatcher): + self.update = update + self.bot = dispatcher.bot + + self.chat_data = None + self.user_data = None + + if update is not None and isinstance(update, Update): + chat = update.effective_chat + user = update.effective_user + + if chat: + self.chat_data = dispatcher.chat_data[chat.id] + if user: + self.user_data = dispatcher.user_data[user.id] + + self.job_queue = dispatcher.job_queue + self.update_queue = dispatcher.update_queue + + self.args = None + self.groups = None + self.groupdict = None diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 45067ee4718..d66b660924d 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -54,11 +54,8 @@ class InlineQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -68,27 +65,32 @@ class InlineQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pattern (:obj:`str` | :obj:`Pattern`, optional): Regex pattern. If not ``None``, ``re.match`` is used on :attr:`telegram.InlineQuery.query` to determine if an update should be handled by this handler. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ def __init__(self, @@ -131,24 +133,22 @@ def check_update(self, update): if self.pattern: if update.inline_query.query: match = re.match(self.pattern, update.inline_query.query) - return bool(match) + if match: + return match else: return True - def collect_optional_args(self, dispatcher, update=None): - optional_args = super(InlineQueryHandler, self).collect_optional_args(dispatcher, update) + def collect_optional_args(self, dispatcher, update=None, check_result=None): + optional_args = super(InlineQueryHandler, self).collect_optional_args(dispatcher, + update, check_result) if self.pattern: - match = re.match(self.pattern, update.inline_query.query) - if self.pass_groups: - optional_args['groups'] = match.groups() + optional_args['groups'] = check_result.groups() if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + optional_args['groupdict'] = check_result.groupdict() return optional_args - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - match = re.match(self.pattern, update.inline_query.query) - - context.groups = match.groups() - context.groupdict = match.groupdict() + context.groups = check_result.groups() + context.groupdict = check_result.groupdict() diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 630e7abddef..4dc6f1b170c 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -55,11 +55,8 @@ class MessageHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: filters (:class:`telegram.ext.BaseFilter`, optional): A filter inheriting from @@ -73,14 +70,18 @@ class MessageHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. message_updates (:obj:`bool`, optional): Should "normal" message updates be handled? Default is ``True``. channel_post_updates (:obj:`bool`, optional): Should channel posts updates be handled? @@ -91,8 +92,7 @@ class MessageHandler(Handler): Default is ``False`` - Deprecated. use edited_updates instead. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. Raises: ValueError @@ -155,16 +155,11 @@ def check_update(self, update): if isinstance(update, Update) and self._is_allowed_update(update): if not self.filters: - res = True + return True else: message = update.effective_message if isinstance(self.filters, list): - res = any(func(message) for func in self.filters) + return any(func(message) for func in self.filters) else: - res = self.filters(message) - - else: - res = False - - return res + return self.filters(message) diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index 3f914000127..90b3b4860ab 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -43,11 +43,8 @@ class PreCheckoutQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -55,38 +52,26 @@ class PreCheckoutQueryHandler(Handler): processed by this handler. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` + DEPRECATED: Please switch to context based handlers. instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ - def __init__(self, - callback, - pass_update_queue=False, - pass_job_queue=False, - pass_user_data=False, - pass_chat_data=False, - use_context=None): - super(PreCheckoutQueryHandler, self).__init__( - callback, - pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) - def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 7504a9da8ce..76845b31a31 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -58,11 +58,8 @@ class RegexHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. @@ -72,21 +69,27 @@ class RegexHandler(Handler): pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. message_updates (:obj:`bool`, optional): Should "normal" message updates be handled? Default is ``True``. channel_post_updates (:obj:`bool`, optional): Should channel posts updates be handled? @@ -97,8 +100,7 @@ class RegexHandler(Handler): Default is ``False`` - Deprecated. use edited_updates instead. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. Raises: ValueError @@ -156,27 +158,24 @@ def check_update(self, update): """ if not isinstance(update, Update) and not update.effective_message: - return False + return None if any([self.message_updates and update.message, self.edited_updates and (update.edited_message or update.edited_channel_post), self.channel_post_updates and update.channel_post]) and \ update.effective_message.text: match = re.match(self.pattern, update.effective_message.text) - return bool(match) - return False - - def collect_optional_args(self, dispatcher, update=None): - optional_args = super(RegexHandler, self).collect_optional_args(dispatcher, update) - match = re.match(self.pattern, update.effective_message.text) + if match: + return match + def collect_optional_args(self, dispatcher, update=None, check_result=None): + optional_args = super(RegexHandler, self).collect_optional_args(dispatcher, update, + check_result) if self.pass_groups: - optional_args['groups'] = match.groups() + optional_args['groups'] = check_result.groups() if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + optional_args['groupdict'] = check_result.groupdict() return optional_args - def collect_additional_context(self, context, update, dispatcher): - match = re.match(self.pattern, update.effective_message.text) - - context.groups = match.groups() - context.groupdict = match.groupdict() + def collect_additional_context(self, context, update, dispatcher, check_result): + context.groups = check_result.groups() + context.groupdict = check_result.groupdict() diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index 0390c0830d0..b005cc05fae 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -43,11 +43,8 @@ class ShippingQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). + Note that this is deprecated, please switch to context based handlers. See + https://git.io/vpVe8 for more info. Args: callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -57,36 +54,24 @@ class ShippingQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ - def __init__(self, - callback, - pass_update_queue=False, - pass_job_queue=False, - pass_user_data=False, - pass_chat_data=False, - use_context=None): - super(ShippingQueryHandler, self).__init__( - callback, - pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) - def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 2ec8cd02a81..7c043f548e3 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -42,12 +42,6 @@ class StringCommandHandler(Handler): use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). - - Args: command (:obj:`str`): The command this handler should listen for. callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -57,18 +51,20 @@ class StringCommandHandler(Handler): arguments passed to the command as a keyword argument called ``args``. It will contain a list of strings, which is the text following the command split on single or consecutive whitespace characters. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ @@ -101,11 +97,13 @@ def check_update(self, update): return (isinstance(update, string_types) and update.startswith('/') and update[1:].split(' ')[0] == self.command) - def collect_optional_args(self, dispatcher, update=None): - optional_args = super(StringCommandHandler, self).collect_optional_args(dispatcher, update) + def collect_optional_args(self, dispatcher, update=None, check_result=None): + optional_args = super(StringCommandHandler, self).collect_optional_args(dispatcher, + update, + check_result) if self.pass_args: optional_args['args'] = update.split()[1:] return optional_args - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): context.args = update.split()[1:] diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index eca5b166730..cc0a1ba3069 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -49,11 +49,6 @@ class StringRegexHandler(Handler): use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). - Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. @@ -62,21 +57,24 @@ class StringRegexHandler(Handler): pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` + DEPRECATED: Please switch to context based handlers. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ @@ -111,22 +109,22 @@ def check_update(self, update): :obj:`bool` """ - return isinstance(update, string_types) and bool(re.match(self.pattern, update)) - - def collect_optional_args(self, dispatcher, update=None): - optional_args = super(StringRegexHandler, self).collect_optional_args(dispatcher, update) - if self.pattern: + if isinstance(update, string_types): match = re.match(self.pattern, update) + if match: + return match + def collect_optional_args(self, dispatcher, update=None, check_result=None): + optional_args = super(StringRegexHandler, self).collect_optional_args(dispatcher, + update, check_result) + if self.pattern: if self.pass_groups: - optional_args['groups'] = match.groups() + optional_args['groups'] = check_result.groups() if self.pass_groupdict: - optional_args['groupdict'] = match.groupdict() + optional_args['groupdict'] = check_result.groupdict() return optional_args - def collect_additional_context(self, context, update, dispatcher): + def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - match = re.match(self.pattern, update) - - context.groups = match.groups() - context.groupdict = match.groupdict() + context.groups = check_result.groups() + context.groupdict = check_result.groupdict() diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index 67fb7c615a1..f9f4f82a81d 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -36,11 +36,6 @@ class TypeHandler(Handler): use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Note: - Instead of using the individual `pass_` you can use :attr:`use_context` and your callback - function will receive a :class:`telegram.ext.Context` object as the only parameter, - instead of the usual (bot, update, others...). - Args: type (:obj:`type`): The ``type`` of updates this handler should process, as determined by ``isinstance`` @@ -53,14 +48,15 @@ class TypeHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. + DEPRECATED: Please switch to context based handlers. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. + DEPRECATED: Please switch to context based handlers. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``True`` if :attr:`callback` has only one parameter. Note that this can - be difficult to determine if :attr:`callback` is decorated - especially on python 2. + Defaults to ``False`` for while the old `pass_` method is in deprecation. """ diff --git a/tests/test_callbackqueryhandler.py b/tests/test_callbackqueryhandler.py index d24ef4ef3e4..5cabfa1dbf7 100644 --- a/tests/test_callbackqueryhandler.py +++ b/tests/test_callbackqueryhandler.py @@ -22,7 +22,8 @@ from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CallbackQueryHandler, Context, JobQueue +from telegram.ext import CallbackQueryHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -82,24 +83,24 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' data'} - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and context.chat_data is None and - isinstance(context.callback_query, CallbackQuery)) + isinstance(update.callback_query, CallbackQuery)) - def callback_context_pattern(self, context): + def callback_context_pattern(self, update, context): if context.groups: self.test_flag = context.groups == ('t', ' data') if context.groupdict: self.test_flag = context.groupdict == {'begin': 't', 'end': ' data'} def test_basic(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_basic) + handler = CallbackQueryHandler(self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(callback_query) @@ -108,7 +109,7 @@ def test_basic(self, dp, callback_query): assert self.test_flag def test_with_pattern(self, callback_query): - handler = CallbackQueryHandler(self.callback_basic, pattern='.*est.*') + handler = CallbackQueryHandler(self.callback_basic, use_context=False, pattern='.*est.*') assert handler.check_update(callback_query) @@ -116,7 +117,7 @@ def test_with_pattern(self, callback_query): assert not handler.check_update(callback_query) def test_with_passing_group_dict(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_group, + handler = CallbackQueryHandler(self.callback_group, use_context=False, pattern='(?P.*)est(?P.*)', pass_groups=True) dp.add_handler(handler) @@ -125,7 +126,7 @@ def test_with_passing_group_dict(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_group, + handler = CallbackQueryHandler(self.callback_group, use_context=False, pattern='(?P.*)est(?P.*)', pass_groupdict=True) dp.add_handler(handler) @@ -135,14 +136,16 @@ def test_with_passing_group_dict(self, dp, callback_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_data_1, pass_user_data=True) + handler = CallbackQueryHandler(self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) dp.process_update(callback_query) assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_data_1, pass_chat_data=True) + handler = CallbackQueryHandler(self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -150,7 +153,8 @@ def test_pass_user_or_chat_data(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_data_2, pass_chat_data=True, + handler = CallbackQueryHandler(self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -159,14 +163,16 @@ def test_pass_user_or_chat_data(self, dp, callback_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_queue_1, pass_job_queue=True) + handler = CallbackQueryHandler(self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update(callback_query) assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_queue_1, pass_update_queue=True) + handler = CallbackQueryHandler(self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -174,7 +180,8 @@ def test_pass_job_or_update_queue(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_queue_2, pass_job_queue=True, + handler = CallbackQueryHandler(self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -183,26 +190,24 @@ def test_pass_job_or_update_queue(self, dp, callback_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = CallbackQueryHandler(self.callback_basic) + handler = CallbackQueryHandler(self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_context) + handler = CallbackQueryHandler(self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(callback_query) assert self.test_flag - def test_not_context(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(callback_query) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + CallbackQueryHandler(self.callback_context) def test_context_pattern(self, dp, callback_query): handler = CallbackQueryHandler(self.callback_context_pattern, - pattern=r'(?P.*)est(?P.*)') + pattern=r'(?P.*)est(?P.*)', + use_context=True) dp.add_handler(handler) dp.process_update(callback_query) @@ -210,7 +215,8 @@ def test_context_pattern(self, dp, callback_query): dp.remove_handler(handler) handler = CallbackQueryHandler(self.callback_context_pattern, - pattern=r'(t)est(.*)') + pattern=r'(t)est(.*)', + use_context=True) dp.add_handler(handler) dp.process_update(callback_query) diff --git a/tests/test_choseninlineresulthandler.py b/tests/test_choseninlineresulthandler.py index a2993e00817..79a8536a9d4 100644 --- a/tests/test_choseninlineresulthandler.py +++ b/tests/test_choseninlineresulthandler.py @@ -22,7 +22,8 @@ from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import ChosenInlineResultHandler, Context, JobQueue +from telegram.ext import ChosenInlineResultHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -79,18 +80,18 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and context.chat_data is None and - isinstance(context.chosen_inline_result, ChosenInlineResult)) + isinstance(update.chosen_inline_result, ChosenInlineResult)) def test_basic(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_basic) + handler = ChosenInlineResultHandler(self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(chosen_inline_result) @@ -98,14 +99,16 @@ def test_basic(self, dp, chosen_inline_result): assert self.test_flag def test_pass_user_or_chat_data(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_data_1, pass_user_data=True) + handler = ChosenInlineResultHandler(self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) dp.process_update(chosen_inline_result) assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_data_1, pass_chat_data=True) + handler = ChosenInlineResultHandler(self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -113,8 +116,8 @@ def test_pass_user_or_chat_data(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_data_2, pass_chat_data=True, - pass_user_data=True) + handler = ChosenInlineResultHandler(self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) self.test_flag = False @@ -122,14 +125,16 @@ def test_pass_user_or_chat_data(self, dp, chosen_inline_result): assert self.test_flag def test_pass_job_or_update_queue(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_queue_1, pass_job_queue=True) + handler = ChosenInlineResultHandler(self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update(chosen_inline_result) assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_queue_1, pass_update_queue=True) + handler = ChosenInlineResultHandler(self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -137,8 +142,8 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_queue_2, pass_job_queue=True, - pass_update_queue=True) + handler = ChosenInlineResultHandler(self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -146,19 +151,16 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): assert self.test_flag def test_other_update_types(self, false_update): - handler = ChosenInlineResultHandler(self.callback_basic) + handler = ChosenInlineResultHandler(self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_context) + handler = ChosenInlineResultHandler(self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(chosen_inline_result) assert self.test_flag - def test_not_context(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(chosen_inline_result) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + ChosenInlineResultHandler(self.callback_context) diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index 84ef564804c..41b4f281189 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -22,7 +22,8 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CommandHandler, Filters, BaseFilter, Context, JobQueue +from telegram.ext import CommandHandler, Filters, BaseFilter, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='test') @@ -84,21 +85,21 @@ def ch_callback_args(self, bot, update, args): else: self.test_flag = args == ['one', 'two'] - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and isinstance(context.chat_data, dict) and - isinstance(context.message, Message)) + isinstance(update.message, Message)) - def callback_context_args(self, context): + def callback_context_args(self, update, context): self.test_flag = context.args == ['one', 'two'] def test_basic(self, dp, message): - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) message.text = '/test' @@ -116,7 +117,7 @@ def test_basic(self, dp, message): assert not handler.check_update(Update(0, message)) def test_command_list(self, message): - handler = CommandHandler(['test', 'start'], self.callback_basic) + handler = CommandHandler(['test', 'start'], self.callback_basic, use_context=False) message.text = '/test' assert handler.check_update(Update(0, message)) @@ -128,7 +129,8 @@ def test_command_list(self, message): assert not handler.check_update(Update(0, message)) def test_edited(self, message): - handler = CommandHandler('test', self.callback_basic, allow_edited=False) + handler = CommandHandler('test', self.callback_basic, use_context=False, + allow_edited=False) message.text = '/test' assert handler.check_update(Update(0, message)) @@ -138,7 +140,7 @@ def test_edited(self, message): assert handler.check_update(Update(0, edited_message=message)) def test_directed_commands(self, message): - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) message.text = '/test@{}'.format(message.bot.username) assert handler.check_update(Update(0, message)) @@ -147,7 +149,7 @@ def test_directed_commands(self, message): assert not handler.check_update(Update(0, message)) def test_with_filter(self, message): - handler = CommandHandler('test', self.callback_basic, Filters.group) + handler = CommandHandler('test', self.callback_basic, Filters.group, use_context=False) message.chat = Chat(-23, 'group') message.text = '/test' @@ -157,7 +159,7 @@ def test_with_filter(self, message): assert not handler.check_update(Update(0, message)) def test_pass_args(self, dp, message): - handler = CommandHandler('test', self.ch_callback_args, pass_args=True) + handler = CommandHandler('test', self.ch_callback_args, use_context=False, pass_args=True) dp.add_handler(handler) message.text = '/test' @@ -180,7 +182,7 @@ def test_pass_args(self, dp, message): assert self.test_flag def test_newline(self, dp, message): - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) message.text = '/test\nfoobar' @@ -190,7 +192,7 @@ def test_newline(self, dp, message): def test_single_char(self, dp, message): # Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/871 - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) message.text = 'a' @@ -198,7 +200,7 @@ def test_single_char(self, dp, message): def test_single_slash(self, dp, message): # Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/871 - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) message.text = '/' @@ -208,7 +210,8 @@ def test_single_slash(self, dp, message): assert not handler.check_update(Update(0, message)) def test_pass_user_or_chat_data(self, dp, message): - handler = CommandHandler('test', self.callback_data_1, pass_user_data=True) + handler = CommandHandler('test', self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) message.text = '/test' @@ -216,7 +219,8 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_data_1, pass_chat_data=True) + handler = CommandHandler('test', self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -224,7 +228,8 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_data_2, pass_chat_data=True, + handler = CommandHandler('test', self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -233,7 +238,8 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = CommandHandler('test', self.callback_queue_1, pass_job_queue=True) + handler = CommandHandler('test', self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) message.text = '/test' @@ -241,7 +247,8 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_queue_1, pass_update_queue=True) + handler = CommandHandler('test', self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -249,7 +256,8 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_queue_2, pass_job_queue=True, + handler = CommandHandler('test', self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -258,7 +266,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = CommandHandler('test', self.callback_basic) + handler = CommandHandler('test', self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_filters_for_wrong_command(self, message): @@ -273,7 +281,8 @@ def filter(self, message): test_filter = TestFilter() - handler = CommandHandler('foo', self.callback_basic, filters=test_filter) + handler = CommandHandler('foo', self.callback_basic, use_context=False, + filters=test_filter) message.text = '/bar' handler.check_update(Update(0, message=message)) @@ -281,7 +290,7 @@ def filter(self, message): assert not test_filter.tested def test_context(self, dp, message): - handler = CommandHandler('test', self.callback_context) + handler = CommandHandler('test', self.callback_context, use_context=True) dp.add_handler(handler) message.text = '/test' @@ -289,17 +298,12 @@ def test_context(self, dp, message): dp.process_update(Update(0, message)) assert self.test_flag - def test_not_context(self, dp, message): - handler = CommandHandler('test', self.callback_context, use_context=False) - dp.add_handler(handler) - - message.text = '/test' - assert handler.check_update(Update(0, message)) - dp.process_update(Update(0, message)) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + CommandHandler('test', self.callback_context) def test_context_args(self, dp, message): - handler = CommandHandler('test', self.callback_context_args) + handler = CommandHandler('test', self.callback_context_args, use_context=True) dp.add_handler(handler) message.text = '/test' diff --git a/tests/test_conversationhandler.py b/tests/test_conversationhandler.py index 7f531ff36ba..51967db9d38 100644 --- a/tests/test_conversationhandler.py +++ b/tests/test_conversationhandler.py @@ -50,21 +50,22 @@ class TestConversationHandler(object): @pytest.fixture(autouse=True) def reset(self): self.current_state = dict() - self.entry_points = [CommandHandler('start', self.start)] + self.entry_points = [CommandHandler('start', self.start, use_context=False)] self.states = { - self.THIRSTY: [CommandHandler('brew', self.brew), CommandHandler('wait', self.start)], - self.BREWING: [CommandHandler('pourCoffee', self.drink)], + self.THIRSTY: [CommandHandler('brew', self.brew, use_context=False), + CommandHandler('wait', self.start, use_context=False)], + self.BREWING: [CommandHandler('pourCoffee', self.drink, use_context=False)], self.DRINKING: - [CommandHandler('startCoding', self.code), - CommandHandler('drinkMore', self.drink), - CommandHandler('end', self.end)], + [CommandHandler('startCoding', self.code, use_context=False), + CommandHandler('drinkMore', self.drink, use_context=False), + CommandHandler('end', self.end, use_context=False)], self.CODING: [ - CommandHandler('keepCoding', self.code), - CommandHandler('gettingThirsty', self.start), - CommandHandler('drinkMore', self.drink) + CommandHandler('keepCoding', self.code, use_context=False), + CommandHandler('gettingThirsty', self.start, use_context=False), + CommandHandler('drinkMore', self.drink, use_context=False) ], } - self.fallbacks = [CommandHandler('eat', self.start)] + self.fallbacks = [CommandHandler('eat', self.start, use_context=False)] # State handlers def _set_state(self, update, state): @@ -232,9 +233,9 @@ def two(bot, update): return ConversationHandler.END handler = ConversationHandler( - entry_points=[CallbackQueryHandler(entry)], - states={1: [CallbackQueryHandler(one)], - 2: [CallbackQueryHandler(two)]}, + entry_points=[CallbackQueryHandler(entry, use_context=False)], + states={1: [CallbackQueryHandler(one, use_context=False)], + 2: [CallbackQueryHandler(two, use_context=False)]}, fallbacks=[], per_message=True) dp.add_handler(handler) @@ -260,7 +261,8 @@ def two(bot, update): def test_end_on_first_message(self, dp, bot, user1): handler = ConversationHandler( - entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) + entry_points=[CommandHandler('start', self.start_end, use_context=False)], states={}, + fallbacks=[]) dp.add_handler(handler) # User starts the state machine and immediately ends it. @@ -272,7 +274,8 @@ def test_end_on_first_message_async(self, dp, bot, user1): start_end_async = (lambda bot, update: dp.run_async(self.start_end, bot, update)) handler = ConversationHandler( - entry_points=[CommandHandler('start', start_end_async)], states={}, fallbacks=[]) + entry_points=[CommandHandler('start', start_end_async, use_context=False)], states={}, + fallbacks=[]) dp.add_handler(handler) # User starts the state machine with an async function that immediately ends the @@ -291,20 +294,23 @@ def test_end_on_first_message_async(self, dp, bot, user1): def test_per_chat_message_without_chat(self, bot, user1): handler = ConversationHandler( - entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) + entry_points=[CommandHandler('start', self.start_end, use_context=False)], states={}, + fallbacks=[]) cbq = CallbackQuery(0, user1, None, None, bot=bot) update = Update(0, callback_query=cbq) assert not handler.check_update(update) def test_channel_message_without_chat(self, bot): - handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], + handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end, + use_context=False)], states={}, fallbacks=[]) message = Message(0, None, None, Chat(0, Chat.CHANNEL, 'Misses Test'), bot=bot) update = Update(0, message=message) assert not handler.check_update(update) def test_all_update_types(self, dp, bot, user1): - handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], + handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end, + use_context=False)], states={}, fallbacks=[]) message = Message(0, user1, None, self.group, text='ignore', bot=bot) callback_query = CallbackQuery(0, user1, None, message=message, data='data', bot=bot) diff --git a/tests/test_inlinequeryhandler.py b/tests/test_inlinequeryhandler.py index ec99c0ac4db..f03ddc4e831 100644 --- a/tests/test_inlinequeryhandler.py +++ b/tests/test_inlinequeryhandler.py @@ -22,7 +22,8 @@ from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery, Location) -from telegram.ext import InlineQueryHandler, Context, JobQueue +from telegram.ext import InlineQueryHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -86,24 +87,24 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' query'} - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and context.chat_data is None and - isinstance(context.inline_query, InlineQuery)) + isinstance(update.inline_query, InlineQuery)) - def callback_context_pattern(self, context): + def callback_context_pattern(self, update, context): if context.groups: self.test_flag = context.groups == ('t', ' query') if context.groupdict: self.test_flag = context.groupdict == {'begin': 't', 'end': ' query'} def test_basic(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_basic) + handler = InlineQueryHandler(self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(inline_query) @@ -112,7 +113,8 @@ def test_basic(self, dp, inline_query): assert self.test_flag def test_with_pattern(self, inline_query): - handler = InlineQueryHandler(self.callback_basic, pattern='(?P.*)est(?P.*)') + handler = InlineQueryHandler(self.callback_basic, use_context=False, + pattern='(?P.*)est(?P.*)') assert handler.check_update(inline_query) @@ -120,7 +122,7 @@ def test_with_pattern(self, inline_query): assert not handler.check_update(inline_query) def test_with_passing_group_dict(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_group, + handler = InlineQueryHandler(self.callback_group, use_context=False, pattern='(?P.*)est(?P.*)', pass_groups=True) dp.add_handler(handler) @@ -129,7 +131,7 @@ def test_with_passing_group_dict(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_group, + handler = InlineQueryHandler(self.callback_group, use_context=False, pattern='(?P.*)est(?P.*)', pass_groupdict=True) dp.add_handler(handler) @@ -139,14 +141,14 @@ def test_with_passing_group_dict(self, dp, inline_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_data_1, pass_user_data=True) + handler = InlineQueryHandler(self.callback_data_1, use_context=False, pass_user_data=True) dp.add_handler(handler) dp.process_update(inline_query) assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_data_1, pass_chat_data=True) + handler = InlineQueryHandler(self.callback_data_1, use_context=False, pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -154,7 +156,7 @@ def test_pass_user_or_chat_data(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_data_2, pass_chat_data=True, + handler = InlineQueryHandler(self.callback_data_2, use_context=False, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -163,14 +165,15 @@ def test_pass_user_or_chat_data(self, dp, inline_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_queue_1, pass_job_queue=True) + handler = InlineQueryHandler(self.callback_queue_1, use_context=False, pass_job_queue=True) dp.add_handler(handler) dp.process_update(inline_query) assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_queue_1, pass_update_queue=True) + handler = InlineQueryHandler(self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -178,7 +181,7 @@ def test_pass_job_or_update_queue(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_queue_2, pass_job_queue=True, + handler = InlineQueryHandler(self.callback_queue_2, use_context=False, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -187,26 +190,24 @@ def test_pass_job_or_update_queue(self, dp, inline_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = InlineQueryHandler(self.callback_basic) + handler = InlineQueryHandler(self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_context) + handler = InlineQueryHandler(self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(inline_query) assert self.test_flag - def test_not_context(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(inline_query) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + InlineQueryHandler(self.callback_context) def test_context_pattern(self, dp, inline_query): handler = InlineQueryHandler(self.callback_context_pattern, - pattern=r'(?P.*)est(?P.*)') + pattern=r'(?P.*)est(?P.*)', + use_context=True) dp.add_handler(handler) dp.process_update(inline_query) @@ -214,7 +215,8 @@ def test_context_pattern(self, dp, inline_query): dp.remove_handler(handler) handler = InlineQueryHandler(self.callback_context_pattern, - pattern=r'(t)est(.*)') + pattern=r'(t)est(.*)', + use_context=True) dp.add_handler(handler) dp.process_update(inline_query) diff --git a/tests/test_messagehandler.py b/tests/test_messagehandler.py index e4dd522a7a2..f87bff7cd72 100644 --- a/tests/test_messagehandler.py +++ b/tests/test_messagehandler.py @@ -22,7 +22,8 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import Filters, MessageHandler, Context, JobQueue +from telegram.ext import Filters, MessageHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -73,27 +74,27 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) - def callback_context(self, context): + def callback_context(self, update, context): self.test_flag = ( - isinstance(context, Context) and + isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.chat_data, dict) and ( (isinstance(context.user_data, dict) and - (isinstance(context.message, Message) or - isinstance(context.edited_message, Message))) + (isinstance(update.message, Message) or + isinstance(update.edited_message, Message))) or (context.user_data is None and - (isinstance(context.channel_post, Message) or - isinstance(context.edited_channel_post, Message))) + (isinstance(update.channel_post, Message) or + isinstance(update.edited_channel_post, Message))) ) ) def test_basic(self, dp, message): - handler = MessageHandler(None, self.callback_basic) + handler = MessageHandler(None, self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(Update(0, message)) @@ -101,7 +102,7 @@ def test_basic(self, dp, message): assert self.test_flag def test_edited(self, message): - handler = MessageHandler(None, self.callback_basic, edited_updates=True, + handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True, message_updates=False, channel_post_updates=False) assert handler.check_update(Update(0, edited_message=message)) @@ -110,8 +111,9 @@ def test_edited(self, message): assert handler.check_update(Update(0, edited_channel_post=message)) def test_channel_post(self, message): - handler = MessageHandler(None, self.callback_basic, edited_updates=False, - message_updates=False, channel_post_updates=True) + handler = MessageHandler(None, self.callback_basic, use_context=False, + edited_updates=False, message_updates=False, + channel_post_updates=True) assert not handler.check_update(Update(0, edited_message=message)) assert not handler.check_update(Update(0, message=message)) @@ -119,7 +121,7 @@ def test_channel_post(self, message): assert not handler.check_update(Update(0, edited_channel_post=message)) def test_multiple_flags(self, message): - handler = MessageHandler(None, self.callback_basic, edited_updates=True, + handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True, message_updates=True, channel_post_updates=True) assert handler.check_update(Update(0, edited_message=message)) @@ -129,8 +131,9 @@ def test_multiple_flags(self, message): def test_allow_edited(self, message): with pytest.warns(UserWarning): - handler = MessageHandler(None, self.callback_basic, message_updates=True, - allow_edited=True, channel_post_updates=False) + handler = MessageHandler(None, self.callback_basic, use_context=False, + message_updates=True, allow_edited=True, + channel_post_updates=False) assert handler.check_update(Update(0, edited_message=message)) assert handler.check_update(Update(0, message=message)) @@ -139,11 +142,11 @@ def test_allow_edited(self, message): def test_none_allowed(self): with pytest.raises(ValueError, match='are all False'): - MessageHandler(None, self.callback_basic, message_updates=False, + MessageHandler(None, self.callback_basic, use_context=False, message_updates=False, channel_post_updates=False, edited_updates=False) def test_with_filter(self, message): - handler = MessageHandler(Filters.command, self.callback_basic) + handler = MessageHandler(Filters.command, self.callback_basic, use_context=False) message.text = '/test' assert handler.check_update(Update(0, message)) @@ -152,14 +155,16 @@ def test_with_filter(self, message): assert not handler.check_update(Update(0, message)) def test_pass_user_or_chat_data(self, dp, message): - handler = MessageHandler(None, self.callback_data_1, pass_user_data=True) + handler = MessageHandler(None, self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_data_1, pass_chat_data=True) + handler = MessageHandler(None, self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -167,8 +172,8 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_data_2, pass_chat_data=True, - pass_user_data=True) + handler = MessageHandler(None, self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) self.test_flag = False @@ -176,14 +181,16 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = MessageHandler(None, self.callback_queue_1, pass_job_queue=True) + handler = MessageHandler(None, self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_queue_1, pass_update_queue=True) + handler = MessageHandler(None, self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -191,8 +198,8 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_queue_2, pass_job_queue=True, - pass_update_queue=True) + handler = MessageHandler(None, self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -200,12 +207,12 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = MessageHandler(None, self.callback_basic, edited_updates=True) + handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True) assert not handler.check_update(false_update) def test_context(self, dp, message): - handler = MessageHandler(None, self.callback_context, edited_updates=True, - channel_post_updates=True) + handler = MessageHandler(None, self.callback_context, use_context=True, + edited_updates=True, channel_post_updates=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) @@ -223,9 +230,6 @@ def test_context(self, dp, message): dp.process_update(Update(0, edited_channel_post=message)) assert self.test_flag - def test_not_context(self, dp, message): - handler = MessageHandler(None, self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(Update(0, message=message)) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + MessageHandler(None, self.callback_context) diff --git a/tests/test_precheckoutqueryhandler.py b/tests/test_precheckoutqueryhandler.py index 061492ce733..e325980310c 100644 --- a/tests/test_precheckoutqueryhandler.py +++ b/tests/test_precheckoutqueryhandler.py @@ -22,7 +22,8 @@ from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import PreCheckoutQueryHandler, Context, JobQueue +from telegram.ext import PreCheckoutQueryHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -79,18 +80,18 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and context.chat_data is None and - isinstance(context.pre_checkout_query, PreCheckoutQuery)) + isinstance(update.pre_checkout_query, PreCheckoutQuery)) def test_basic(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_basic) + handler = PreCheckoutQueryHandler(self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(pre_checkout_query) @@ -98,14 +99,16 @@ def test_basic(self, dp, pre_checkout_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_data_1, pass_user_data=True) + handler = PreCheckoutQueryHandler(self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) dp.process_update(pre_checkout_query) assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_data_1, pass_chat_data=True) + handler = PreCheckoutQueryHandler(self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -113,7 +116,8 @@ def test_pass_user_or_chat_data(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_data_2, pass_chat_data=True, + handler = PreCheckoutQueryHandler(self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -122,14 +126,16 @@ def test_pass_user_or_chat_data(self, dp, pre_checkout_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_queue_1, pass_job_queue=True) + handler = PreCheckoutQueryHandler(self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update(pre_checkout_query) assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_queue_1, pass_update_queue=True) + handler = PreCheckoutQueryHandler(self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -137,7 +143,8 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_queue_2, pass_job_queue=True, + handler = PreCheckoutQueryHandler(self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -146,19 +153,16 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = PreCheckoutQueryHandler(self.callback_basic) + handler = PreCheckoutQueryHandler(self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_context) + handler = PreCheckoutQueryHandler(self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(pre_checkout_query) assert self.test_flag - def test_not_context(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(pre_checkout_query) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + PreCheckoutQueryHandler(self.callback_context) diff --git a/tests/test_regexhandler.py b/tests/test_regexhandler.py index f14e8c8c48e..1a14c3dc586 100644 --- a/tests/test_regexhandler.py +++ b/tests/test_regexhandler.py @@ -22,7 +22,8 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import RegexHandler, Context, JobQueue +from telegram.ext import RegexHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -79,24 +80,24 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' message'} - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and isinstance(context.chat_data, dict) and - isinstance(context.message, Message)) + isinstance(update.message, Message)) - def callback_context_pattern(self, context): + def callback_context_pattern(self, update, context): if context.groups: self.test_flag = context.groups == ('t', ' message') if context.groupdict: self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} def test_basic(self, dp, message): - handler = RegexHandler('.*', self.callback_basic) + handler = RegexHandler('.*', self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(Update(0, message)) @@ -104,15 +105,16 @@ def test_basic(self, dp, message): assert self.test_flag def test_pattern(self, message): - handler = RegexHandler('.*est.*', self.callback_basic) + handler = RegexHandler('.*est.*', self.callback_basic, use_context=False) assert handler.check_update(Update(0, message)) - handler = RegexHandler('.*not in here.*', self.callback_basic) + handler = RegexHandler('.*not in here.*', self.callback_basic, use_context=False) assert not handler.check_update(Update(0, message)) def test_with_passing_group_dict(self, dp, message): handler = RegexHandler('(?P.*)est(?P.*)', self.callback_group, + use_context=False, pass_groups=True) dp.add_handler(handler) @@ -121,6 +123,7 @@ def test_with_passing_group_dict(self, dp, message): dp.remove_handler(handler) handler = RegexHandler('(?P.*)est(?P.*)', self.callback_group, + use_context=False, pass_groupdict=True) dp.add_handler(handler) @@ -129,7 +132,7 @@ def test_with_passing_group_dict(self, dp, message): assert self.test_flag def test_edited(self, message): - handler = RegexHandler('.*', self.callback_basic, edited_updates=True, + handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True, message_updates=False, channel_post_updates=False) assert handler.check_update(Update(0, edited_message=message)) @@ -138,7 +141,7 @@ def test_edited(self, message): assert handler.check_update(Update(0, edited_channel_post=message)) def test_channel_post(self, message): - handler = RegexHandler('.*', self.callback_basic, edited_updates=False, + handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=False, message_updates=False, channel_post_updates=True) assert not handler.check_update(Update(0, edited_message=message)) @@ -147,7 +150,7 @@ def test_channel_post(self, message): assert not handler.check_update(Update(0, edited_channel_post=message)) def test_multiple_flags(self, message): - handler = RegexHandler('.*', self.callback_basic, edited_updates=True, + handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True, message_updates=True, channel_post_updates=True) assert handler.check_update(Update(0, edited_message=message)) @@ -157,7 +160,8 @@ def test_multiple_flags(self, message): def test_allow_edited(self, message): with pytest.warns(UserWarning): - handler = RegexHandler('.*', self.callback_basic, message_updates=True, + handler = RegexHandler('.*', self.callback_basic, use_context=False, + message_updates=True, allow_edited=True) assert handler.check_update(Update(0, edited_message=message)) @@ -167,18 +171,18 @@ def test_allow_edited(self, message): def test_none_allowed(self): with pytest.raises(ValueError, match='are all False'): - RegexHandler('.*', self.callback_basic, message_updates=False, + RegexHandler('.*', self.callback_basic, use_context=False, message_updates=False, channel_post_updates=False, edited_updates=False) def test_pass_user_or_chat_data(self, dp, message): - handler = RegexHandler('.*', self.callback_data_1, pass_user_data=True) + handler = RegexHandler('.*', self.callback_data_1, use_context=False, pass_user_data=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_data_1, pass_chat_data=True) + handler = RegexHandler('.*', self.callback_data_1, use_context=False, pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -186,7 +190,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_data_2, pass_chat_data=True, + handler = RegexHandler('.*', self.callback_data_2, use_context=False, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -195,14 +199,15 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = RegexHandler('.*', self.callback_queue_1, pass_job_queue=True) + handler = RegexHandler('.*', self.callback_queue_1, use_context=False, pass_job_queue=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_queue_1, pass_update_queue=True) + handler = RegexHandler('.*', self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -210,7 +215,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_queue_2, pass_job_queue=True, + handler = RegexHandler('.*', self.callback_queue_2, use_context=False, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -219,32 +224,29 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = RegexHandler('.*', self.callback_basic, edited_updates=True) + handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True) assert not handler.check_update(false_update) def test_context(self, dp, message): - handler = RegexHandler(r'(t)est(.*)', self.callback_context) + handler = RegexHandler(r'(t)est(.*)', self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag - def test_not_context(self, dp, message): - handler = RegexHandler(r'(t)est(.*)', self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(Update(0, message=message)) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + RegexHandler('test', self.callback_context) def test_context_pattern(self, dp, message): - handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern, use_context=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern, use_context=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) diff --git a/tests/test_shippingqueryhandler.py b/tests/test_shippingqueryhandler.py index 5d5ca042115..564c715320f 100644 --- a/tests/test_shippingqueryhandler.py +++ b/tests/test_shippingqueryhandler.py @@ -22,7 +22,8 @@ from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery, ShippingAddress) -from telegram.ext import ShippingQueryHandler, Context, JobQueue +from telegram.ext import ShippingQueryHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -80,18 +81,18 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, Update) and + isinstance(update, Update) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.user_data, dict) and context.chat_data is None and - isinstance(context.shipping_query, ShippingQuery)) + isinstance(update.shipping_query, ShippingQuery)) def test_basic(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_basic) + handler = ShippingQueryHandler(self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update(shiping_query) @@ -99,14 +100,16 @@ def test_basic(self, dp, shiping_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_data_1, pass_user_data=True) + handler = ShippingQueryHandler(self.callback_data_1, use_context=False, + pass_user_data=True) dp.add_handler(handler) dp.process_update(shiping_query) assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_data_1, pass_chat_data=True) + handler = ShippingQueryHandler(self.callback_data_1, use_context=False, + pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -114,7 +117,8 @@ def test_pass_user_or_chat_data(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_data_2, pass_chat_data=True, + handler = ShippingQueryHandler(self.callback_data_2, use_context=False, + pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -123,14 +127,16 @@ def test_pass_user_or_chat_data(self, dp, shiping_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_queue_1, pass_job_queue=True) + handler = ShippingQueryHandler(self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update(shiping_query) assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_queue_1, pass_update_queue=True) + handler = ShippingQueryHandler(self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -138,7 +144,8 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_queue_2, pass_job_queue=True, + handler = ShippingQueryHandler(self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -147,19 +154,16 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = ShippingQueryHandler(self.callback_basic) + handler = ShippingQueryHandler(self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_context) + handler = ShippingQueryHandler(self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update(shiping_query) assert self.test_flag - def test_not_context(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update(shiping_query) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + ShippingQueryHandler(self.callback_context) diff --git a/tests/test_stringcommandhandler.py b/tests/test_stringcommandhandler.py index 07d4d096adb..f9b0ff9e07a 100644 --- a/tests/test_stringcommandhandler.py +++ b/tests/test_stringcommandhandler.py @@ -22,7 +22,8 @@ from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringCommandHandler, Context, JobQueue +from telegram.ext import StringCommandHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -73,20 +74,20 @@ def sch_callback_args(self, bot, update, args): else: self.test_flag = args == ['one', 'two'] - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, str) and + isinstance(update, str) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and context.user_data is None and context.chat_data is None) - def callback_context_args(self, context): + def callback_context_args(self, update, context): self.test_flag = context.args == ['one', 'two'] def test_basic(self, dp): - handler = StringCommandHandler('test', self.callback_basic) + handler = StringCommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update('/test') @@ -98,7 +99,8 @@ def test_basic(self, dp): assert handler.check_update('/test followed by text') def test_pass_args(self, dp): - handler = StringCommandHandler('test', self.sch_callback_args, pass_args=True) + handler = StringCommandHandler('test', self.sch_callback_args, use_context=False, + pass_args=True) dp.add_handler(handler) dp.process_update('/test') @@ -109,14 +111,16 @@ def test_pass_args(self, dp): assert self.test_flag def test_pass_job_or_update_queue(self, dp): - handler = StringCommandHandler('test', self.callback_queue_1, pass_job_queue=True) + handler = StringCommandHandler('test', self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update('/test') assert self.test_flag dp.remove_handler(handler) - handler = StringCommandHandler('test', self.callback_queue_1, pass_update_queue=True) + handler = StringCommandHandler('test', self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -124,7 +128,8 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringCommandHandler('test', self.callback_queue_2, pass_job_queue=True, + handler = StringCommandHandler('test', self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -133,25 +138,22 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag def test_other_update_types(self, false_update): - handler = StringCommandHandler('test', self.callback_basic) + handler = StringCommandHandler('test', self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp): - handler = StringCommandHandler('test', self.callback_context) + handler = StringCommandHandler('test', self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update('/test') assert self.test_flag - def test_not_context(self, dp): - handler = StringCommandHandler('test', self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update('/test') - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + StringCommandHandler('test', self.callback_context) def test_context_args(self, dp): - handler = StringCommandHandler('test', self.callback_context_args) + handler = StringCommandHandler('test', self.callback_context_args, use_context=True) dp.add_handler(handler) dp.process_update('/test') diff --git a/tests/test_stringregexhandler.py b/tests/test_stringregexhandler.py index 84dcf46fb87..3d0c594d0bc 100644 --- a/tests/test_stringregexhandler.py +++ b/tests/test_stringregexhandler.py @@ -22,7 +22,8 @@ from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringRegexHandler, Context, JobQueue +from telegram.ext import StringRegexHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -73,21 +74,22 @@ def callback_group(self, bot, update, groups=None, groupdict=None): if groupdict is not None: self.test_flag = groupdict == {'begin': 't', 'end': ' message'} - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, str) and + isinstance(update, str) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue)) - def callback_context_pattern(self, context): + def callback_context_pattern(self, update, context): if context.groups: self.test_flag = context.groups == ('t', ' message') if context.groupdict: self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} def test_basic(self, dp): - handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic) + handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic, + use_context=False) dp.add_handler(handler) assert handler.check_update('test message') @@ -98,7 +100,7 @@ def test_basic(self, dp): def test_with_passing_group_dict(self, dp): handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_group, - pass_groups=True) + use_context=False, pass_groups=True) dp.add_handler(handler) dp.process_update('test message') @@ -106,7 +108,7 @@ def test_with_passing_group_dict(self, dp): dp.remove_handler(handler) handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_group, - pass_groupdict=True) + use_context=False, pass_groupdict=True) dp.add_handler(handler) self.test_flag = False @@ -114,14 +116,16 @@ def test_with_passing_group_dict(self, dp): assert self.test_flag def test_pass_job_or_update_queue(self, dp): - handler = StringRegexHandler('test', self.callback_queue_1, pass_job_queue=True) + handler = StringRegexHandler('test', self.callback_queue_1, use_context=False, + pass_job_queue=True) dp.add_handler(handler) dp.process_update('test') assert self.test_flag dp.remove_handler(handler) - handler = StringRegexHandler('test', self.callback_queue_1, pass_update_queue=True) + handler = StringRegexHandler('test', self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -129,8 +133,8 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringRegexHandler('test', self.callback_queue_2, pass_job_queue=True, - pass_update_queue=True) + handler = StringRegexHandler('test', self.callback_queue_2, use_context=False, + pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -138,32 +142,31 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag def test_other_update_types(self, false_update): - handler = StringRegexHandler('test', self.callback_basic) + handler = StringRegexHandler('test', self.callback_basic, use_context=False) assert not handler.check_update(false_update) def test_context(self, dp): - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context) + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update('test message') assert self.test_flag - def test_not_context(self, dp): - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update('test message') - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + StringRegexHandler('test', self.callback_context) def test_context_pattern(self, dp): - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern, + use_context=True) dp.add_handler(handler) dp.process_update('test message') assert self.test_flag dp.remove_handler(handler) - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern, + use_context=True) dp.add_handler(handler) dp.process_update('test message') diff --git a/tests/test_typehandler.py b/tests/test_typehandler.py index 110a3d5a260..724e9ec7cc0 100644 --- a/tests/test_typehandler.py +++ b/tests/test_typehandler.py @@ -22,7 +22,8 @@ import pytest from telegram import Bot -from telegram.ext import TypeHandler, Context, JobQueue +from telegram.ext import TypeHandler, HandlerContext, JobQueue +from telegram.utils.deprecate import TelegramDeprecationWarning class TestTypeHandler(object): @@ -43,17 +44,17 @@ def callback_queue_1(self, bot, update, job_queue=None, update_queue=None): def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) - def callback_context(self, context): - self.test_flag = (isinstance(context, Context) and + def callback_context(self, update, context): + self.test_flag = (isinstance(context, HandlerContext) and isinstance(context.bot, Bot) and - isinstance(context.update, dict) and + isinstance(update, dict) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and context.user_data is None and context.chat_data is None) def test_basic(self, dp): - handler = TypeHandler(dict, self.callback_basic) + handler = TypeHandler(dict, self.callback_basic, use_context=False) dp.add_handler(handler) assert handler.check_update({'a': 1, 'b': 2}) @@ -62,20 +63,21 @@ def test_basic(self, dp): assert self.test_flag def test_strict(self): - handler = TypeHandler(dict, self.callback_basic, strict=True) + handler = TypeHandler(dict, self.callback_basic, use_context=False, strict=True) o = OrderedDict({'a': 1, 'b': 2}) assert handler.check_update({'a': 1, 'b': 2}) assert not handler.check_update(o) def test_pass_job_or_update_queue(self, dp): - handler = TypeHandler(dict, self.callback_queue_1, pass_job_queue=True) + handler = TypeHandler(dict, self.callback_queue_1, use_context=False, pass_job_queue=True) dp.add_handler(handler) dp.process_update({'a': 1, 'b': 2}) assert self.test_flag dp.remove_handler(handler) - handler = TypeHandler(dict, self.callback_queue_1, pass_update_queue=True) + handler = TypeHandler(dict, self.callback_queue_1, use_context=False, + pass_update_queue=True) dp.add_handler(handler) self.test_flag = False @@ -83,7 +85,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = TypeHandler(dict, self.callback_queue_2, pass_job_queue=True, + handler = TypeHandler(dict, self.callback_queue_2, use_context=False, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -92,15 +94,12 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag def test_context(self, dp): - handler = TypeHandler(dict, self.callback_context) + handler = TypeHandler(dict, self.callback_context, use_context=True) dp.add_handler(handler) dp.process_update({'a': 1, 'b': 2}) assert self.test_flag - def test_not_context(self, dp): - handler = TypeHandler(dict, self.callback_context, use_context=False) - dp.add_handler(handler) - - dp.process_update({'a': 1, 'b': 2}) - assert not self.test_flag + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + TypeHandler(dict, self.callback_context) From bfec5ead9cbea97c6a79bdb62ed83097b63fcf00 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:43:12 +0200 Subject: [PATCH 10/32] Make CommandHandler no longer support filter lists --- telegram/ext/commandhandler.py | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 542b1eadf1d..d2f7a90aa8f 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -17,8 +17,6 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the CommandHandler class.""" -import warnings - from future.utils import string_types from telegram import Update @@ -126,13 +124,6 @@ def __init__(self, self.allow_edited = allow_edited self.pass_args = pass_args - # We put this up here instead of with the rest of checking code - # in check_update since we don't wanna spam a ton - if isinstance(self.filters, list): - warnings.warn('Using a list of filters in MessageHandler is getting ' - 'deprecated, please use bitwise operators (& and |) ' - 'instead. More info: https://git.io/vPTbc.') - def check_update(self, update): """Determines whether an update should be passed to this handlers :attr:`callback`. @@ -160,18 +151,14 @@ def check_update(self, update): if self.filters is None: return True - elif isinstance(self.filters, list): - return any(func(message) for func in self.filters) - else: - return self.filters(message) + if self.filters(message): + return message.text.split()[1:] def collect_optional_args(self, dispatcher, update=None, check_result=None): optional_args = super(CommandHandler, self).collect_optional_args(dispatcher, update) if self.pass_args: - message = update.message or update.edited_message - optional_args['args'] = message.text.split()[1:] + optional_args['args'] = check_result return optional_args def collect_additional_context(self, context, update, dispatcher, check_result): - message = update.message or update.edited_message - context.args = message.text.split()[1:] + context.args = check_result From da26227417f79348ccdb31573ba681a502146e67 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:45:33 +0200 Subject: [PATCH 11/32] Fix indent (pycharm can be an arse sometimes) --- telegram/ext/conversationhandler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py index 357423cbd15..7ae93d32417 100644 --- a/telegram/ext/conversationhandler.py +++ b/telegram/ext/conversationhandler.py @@ -215,9 +215,9 @@ def check_update(self, update): # Ignore messages in channels if (not isinstance(update, Update) or update.channel_post or - self.per_chat and not update.effective_chat or - self.per_message and not update.callback_query or - update.callback_query and self.per_chat and not update.callback_query.message): + self.per_chat and not update.effective_chat or + self.per_message and not update.callback_query or + update.callback_query and self.per_chat and not update.callback_query.message): return None key = self._get_key(update) From c450a4e122cabac15451095aa19ed9f01cb193b8 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:48:29 +0200 Subject: [PATCH 12/32] Improve readability in conversationhandler --- telegram/ext/conversationhandler.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py index 7ae93d32417..2bbad640fe7 100644 --- a/telegram/ext/conversationhandler.py +++ b/telegram/ext/conversationhandler.py @@ -299,19 +299,19 @@ def handle_update(self, update, dispatcher, check_result): dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update. """ - new_state = check_result[1].handle_update(update, dispatcher, check_result[2]) - current_conversation = check_result[0] - timeout_job = self.timeout_jobs.pop(current_conversation, None) + conversation_key, handler, check_result = check_result + new_state = handler.handle_update(update, dispatcher, check_result) + timeout_job = self.timeout_jobs.pop(conversation_key, None) if timeout_job is not None: timeout_job.schedule_removal() if self.conversation_timeout and new_state != self.END: - self.timeout_jobs[current_conversation] = dispatcher.job_queue.run_once( + self.timeout_jobs[conversation_key] = dispatcher.job_queue.run_once( self._trigger_timeout, self.conversation_timeout, - context=current_conversation + context=conversation_key ) - self.update_state(new_state, current_conversation) + self.update_state(new_state, conversation_key) def update_state(self, new_state, key): if new_state == self.END: From 35c07ddd9f862deec0087ed2f548dfc23c4f9e7e Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:58:11 +0200 Subject: [PATCH 13/32] Make context have Match instead of groups & groupdict --- telegram/ext/callbackqueryhandler.py | 3 +-- telegram/ext/handler.py | 25 ++++++++++--------------- telegram/ext/inlinequeryhandler.py | 3 +-- telegram/ext/regexhandler.py | 3 +-- telegram/ext/stringregexhandler.py | 3 +-- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index af8ca3bed35..5ea0bc330b2 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -152,5 +152,4 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - context.groups = check_result.groups() - context.groupdict = check_result.groupdict() + context.match = check_result diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index a965e45485a..15acf25c1ec 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -133,7 +133,6 @@ def handle_update(self, update, dispatcher, check_result): return self.callback(update, context) else: optional_args = self.collect_optional_args(dispatcher, update, check_result) - return self.callback(dispatcher.bot, update, **optional_args) def collect_additional_context(self, context, update, dispatcher, check_result): @@ -189,10 +188,9 @@ class HandlerContext(object): update from the same chat it will be the same ``dict``. user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each update from the same user it will be the same ``dict``. - groups (:obj:`tuple`, optional): If the associated update originated from a - regex-supported handler, this will contain the ``re.match(pattern, data).groups()``. - groupdict (:obj:`dict`, optional): If the associated update originated from a - regex-supported handler, this will contain the ``re.match(pattern, data).groupdict()``. + match (:obj:`_sre.SRE_Match`): If the associated update originated from a + regex-supported handler, this will contain the object returned from ``re.match( + pattern, string)``. job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the @@ -205,12 +203,16 @@ class HandlerContext(object): characters. """ + chat_data = None + user_data = None + args = None + match = None + def __init__(self, update, dispatcher): self.update = update self.bot = dispatcher.bot - - self.chat_data = None - self.user_data = None + self.job_queue = dispatcher.job_queue + self.update_queue = dispatcher.update_queue if update is not None and isinstance(update, Update): chat = update.effective_chat @@ -220,10 +222,3 @@ def __init__(self, update, dispatcher): self.chat_data = dispatcher.chat_data[chat.id] if user: self.user_data = dispatcher.user_data[user.id] - - self.job_queue = dispatcher.job_queue - self.update_queue = dispatcher.update_queue - - self.args = None - self.groups = None - self.groupdict = None diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index d66b660924d..9777e1ede1a 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -150,5 +150,4 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - context.groups = check_result.groups() - context.groupdict = check_result.groupdict() + context.match = check_result diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 76845b31a31..9fb77f2cd48 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -177,5 +177,4 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): return optional_args def collect_additional_context(self, context, update, dispatcher, check_result): - context.groups = check_result.groups() - context.groupdict = check_result.groupdict() + context.match = check_result diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index cc0a1ba3069..94e606d9f97 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -126,5 +126,4 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): def collect_additional_context(self, context, update, dispatcher, check_result): if self.pattern: - context.groups = check_result.groups() - context.groupdict = check_result.groupdict() + context.match = check_result From b325cc1f006e02912c1c8ba4f6ec012727ccf30c Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:58:28 +0200 Subject: [PATCH 14/32] Remove filter list support from messagehandler too --- telegram/ext/messagehandler.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 4dc6f1b170c..1664957752d 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -130,13 +130,6 @@ def __init__(self, self.channel_post_updates = channel_post_updates self.edited_updates = edited_updates - # We put this up here instead of with the rest of checking code - # in check_update since we don't wanna spam a ton - if isinstance(self.filters, list): - warnings.warn('Using a list of filters in MessageHandler is getting ' - 'deprecated, please use bitwise operators (& and |) ' - 'instead. More info: https://git.io/vPTbc.') - def _is_allowed_update(self, update): return any([self.message_updates and update.message, self.edited_updates and (update.edited_message or update.edited_channel_post), @@ -159,7 +152,6 @@ def check_update(self, update): else: message = update.effective_message - if isinstance(self.filters, list): - return any(func(message) for func in self.filters) - else: - return self.filters(message) + if self.filters is None: + return True + return self.filters(message) From 945a5ec7df7f5a8721f2ab92d037387f62a9d477 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 14:59:46 +0200 Subject: [PATCH 15/32] Small fix to StringCommandHandler --- telegram/ext/stringcommandhandler.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 7c043f548e3..4219162ecde 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -94,16 +94,18 @@ def check_update(self, update): """ - return (isinstance(update, string_types) and update.startswith('/') - and update[1:].split(' ')[0] == self.command) + if isinstance(update, string_types) and update.startswith('/'): + args = update[1:].split(' ') + if args[0] == self.command: + return args def collect_optional_args(self, dispatcher, update=None, check_result=None): optional_args = super(StringCommandHandler, self).collect_optional_args(dispatcher, update, check_result) if self.pass_args: - optional_args['args'] = update.split()[1:] + optional_args['args'] = check_result return optional_args def collect_additional_context(self, context, update, dispatcher, check_result): - context.args = update.split()[1:] + context.args = check_result From 07747f3c8ea7b4a590ce8d696906dcf956c7b14d Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 15:23:21 +0200 Subject: [PATCH 16/32] More small fixes to handlers --- telegram/ext/dispatcher.py | 2 +- telegram/ext/handler.py | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/telegram/ext/dispatcher.py b/telegram/ext/dispatcher.py index 945c6ac8102..2f3790ed961 100644 --- a/telegram/ext/dispatcher.py +++ b/telegram/ext/dispatcher.py @@ -279,7 +279,7 @@ def process_update(self, update): check = handler.check_update(update) if check is not None and check is not False: handler.handle_update(update, self, check) - break + break # Stop processing with any other handler. except DispatcherHandlerStop: diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 15acf25c1ec..fca25562709 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -107,7 +107,9 @@ def check_update(self, update): update (:obj:`str` | :class:`telegram.Update`): The update to be tested. Returns: - :obj:`bool` + Either ``None`` or ``False`` if the update should not be handled. Otherwise an object + that will be passed to :attr:`handle_update` and :attr:`collect_additional_context` + when the update gets handled. """ raise NotImplementedError @@ -121,9 +123,9 @@ def handle_update(self, update, dispatcher, check_result): Note that it can be overridden if needed by the subclassing handler. Args: - check_result: The result from check_update update (:obj:`str` | :class:`telegram.Update`): The update to be handled. dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher to collect optional args. + check_result: The result from check_update """ @@ -139,10 +141,10 @@ def collect_additional_context(self, context, update, dispatcher, check_result): """Prepares additional arguments for the context. Override if handler needs. Args: - check_result: The result from check_update context (:class:`telegram.ext.HandlerContext`): The context. - dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. update (:class:`telegram.Update`): The update to gather chat/user id from. + dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. + check_result: The result from check_update """ pass @@ -153,9 +155,9 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): https://git.io/vpVe8 for more info. Args: - check_result: The result from check_update dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. update (:class:`telegram.Update`): The update to gather chat/user id from. + check_result: The result from check_update """ optional_args = dict() @@ -184,18 +186,18 @@ class HandlerContext(object): Attributes: bot (:class:`telegram.Bot`): The bot associated with this context. + job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the + :class:`telegram.ext.Updater` which can be used to schedule new jobs. + update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the + :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` + which contains new updates and can be used to insert updates. chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each update from the same chat it will be the same ``dict``. user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each update from the same user it will be the same ``dict``. - match (:obj:`_sre.SRE_Match`): If the associated update originated from a + match (:obj:`_sre.SRE_Match`, optional): If the associated update originated from a regex-supported handler, this will contain the object returned from ``re.match( pattern, string)``. - job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the - :class:`telegram.ext.Updater` which can be used to schedule new jobs. - update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the - :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` - which contains new updates and can be used to insert updates. args (List[:obj:`str`], optional): Arguments passed to a command if the associated update originated from a :class:`telegram.ext.CommandHandler` or a :class:`telegram.ext.StringCommandHandler`. It will contain a list of strings, From a54cfaccf3dc2d8b8c6c730f15fe2b160ba5134c Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 15:25:16 +0200 Subject: [PATCH 17/32] Amend CHANGES --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index d570584898e..17863291d34 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,8 @@ Handler overhaul: - Use of `pass_` in handlers is deprecated. - Instead use `use_context=True` and change callback from (bot, update, others...) to (update, context) See https://git.io/vpVe8 for help. - Handlers should be faster due to deduped logic. For those with their own handlers subclass telegram.ext.Handler, this is backwards incompatible. +- Remove the last CamelCase CheckUpdate methods from the handlers we missed earlier. +- Remove the ability to use filter lists in handlers. **2018-04-17** *Released 10.0.2* From 30712c596adace8d48ee9fe507bec46a072d7c16 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 15:55:43 +0200 Subject: [PATCH 18/32] Fix tests and fix bugs raised by tests --- telegram/ext/commandhandler.py | 4 +- telegram/ext/stringcommandhandler.py | 2 +- tests/test_callbackqueryhandler.py | 8 ++-- tests/test_commandhandler.py | 59 +++++++++++++++++----------- tests/test_inlinequeryhandler.py | 8 ++-- tests/test_regexhandler.py | 8 ++-- tests/test_stringcommandhandler.py | 12 ++++-- tests/test_stringregexhandler.py | 8 ++-- 8 files changed, 62 insertions(+), 47 deletions(-) diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index d2f7a90aa8f..51d45d81b07 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -149,9 +149,7 @@ def check_update(self, update): and command[1].lower() == message.bot.username.lower()): return None - if self.filters is None: - return True - if self.filters(message): + if self.filters is None or self.filters(message): return message.text.split()[1:] def collect_optional_args(self, dispatcher, update=None, check_result=None): diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 4219162ecde..3aaa1601933 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -97,7 +97,7 @@ def check_update(self, update): if isinstance(update, string_types) and update.startswith('/'): args = update[1:].split(' ') if args[0] == self.command: - return args + return args[1:] def collect_optional_args(self, dispatcher, update=None, check_result=None): optional_args = super(StringCommandHandler, self).collect_optional_args(dispatcher, diff --git a/tests/test_callbackqueryhandler.py b/tests/test_callbackqueryhandler.py index 5cabfa1dbf7..eef7cd787b1 100644 --- a/tests/test_callbackqueryhandler.py +++ b/tests/test_callbackqueryhandler.py @@ -94,10 +94,10 @@ def callback_context(self, update, context): isinstance(update.callback_query, CallbackQuery)) def callback_context_pattern(self, update, context): - if context.groups: - self.test_flag = context.groups == ('t', ' data') - if context.groupdict: - self.test_flag = context.groupdict == {'begin': 't', 'end': ' data'} + if context.match.groups(): + self.test_flag = context.match.groups() == ('t', ' data') + if context.match.groupdict(): + self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' data'} def test_basic(self, dp, callback_query): handler = CallbackQueryHandler(self.callback_basic, use_context=False) diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index 41b4f281189..c80cdf247e5 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -103,47 +103,55 @@ def test_basic(self, dp, message): dp.add_handler(handler) message.text = '/test' - assert handler.check_update(Update(0, message)) dp.process_update(Update(0, message)) assert self.test_flag message.text = '/nottest' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False message.text = 'test' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False message.text = 'not /test at start' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False def test_command_list(self, message): handler = CommandHandler(['test', 'start'], self.callback_basic, use_context=False) message.text = '/test' - assert handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) message.text = '/start' - assert handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) message.text = '/stop' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False def test_edited(self, message): handler = CommandHandler('test', self.callback_basic, use_context=False, allow_edited=False) message.text = '/test' - assert handler.check_update(Update(0, message)) - assert not handler.check_update(Update(0, edited_message=message)) + check = handler.check_update(Update(0, message)) + assert check is not None and check is not False + check = handler.check_update(Update(0, edited_message=message)) + assert check is None or check is False handler.allow_edited = True - assert handler.check_update(Update(0, message)) - assert handler.check_update(Update(0, edited_message=message)) + check = handler.check_update(Update(0, message)) + assert check is not None and check is not False + check = handler.check_update(Update(0, edited_message=message)) + assert check is not None and check is not False def test_directed_commands(self, message): handler = CommandHandler('test', self.callback_basic, use_context=False) message.text = '/test@{}'.format(message.bot.username) - assert handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is not None and check is not False message.text = '/test@otherbot' assert not handler.check_update(Update(0, message)) @@ -153,10 +161,12 @@ def test_with_filter(self, message): message.chat = Chat(-23, 'group') message.text = '/test' - assert handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is not None and check is not False message.chat = Chat(23, 'private') - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False def test_pass_args(self, dp, message): handler = CommandHandler('test', self.ch_callback_args, use_context=False, pass_args=True) @@ -186,7 +196,8 @@ def test_newline(self, dp, message): dp.add_handler(handler) message.text = '/test\nfoobar' - assert handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is not None and check is not False dp.process_update(Update(0, message)) assert self.test_flag @@ -196,7 +207,8 @@ def test_single_char(self, dp, message): dp.add_handler(handler) message.text = 'a' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False def test_single_slash(self, dp, message): # Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/871 @@ -204,10 +216,12 @@ def test_single_slash(self, dp, message): dp.add_handler(handler) message.text = '/' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False message.text = '/ test' - assert not handler.check_update(Update(0, message)) + check = handler.check_update(Update(0, message)) + assert check is None or check is False def test_pass_user_or_chat_data(self, dp, message): handler = CommandHandler('test', self.callback_data_1, use_context=False, @@ -267,7 +281,8 @@ def test_pass_job_or_update_queue(self, dp, message): def test_other_update_types(self, false_update): handler = CommandHandler('test', self.callback_basic, use_context=False) - assert not handler.check_update(false_update) + check = handler.check_update(false_update) + assert check is None or check is False def test_filters_for_wrong_command(self, message): """Filters should not be executed if the command does not match the handler""" @@ -285,7 +300,8 @@ def filter(self, message): filters=test_filter) message.text = '/bar' - handler.check_update(Update(0, message=message)) + check = handler.check_update(Update(0, message=message)) + assert check is None or check is False assert not test_filter.tested @@ -294,7 +310,6 @@ def test_context(self, dp, message): dp.add_handler(handler) message.text = '/test' - assert handler.check_update(Update(0, message)) dp.process_update(Update(0, message)) assert self.test_flag @@ -307,11 +322,9 @@ def test_context_args(self, dp, message): dp.add_handler(handler) message.text = '/test' - assert handler.check_update(Update(0, message)) dp.process_update(Update(0, message)) assert not self.test_flag message.text = '/test one two' - assert handler.check_update(Update(0, message)) dp.process_update(Update(0, message)) assert self.test_flag diff --git a/tests/test_inlinequeryhandler.py b/tests/test_inlinequeryhandler.py index f03ddc4e831..690e0a0c94f 100644 --- a/tests/test_inlinequeryhandler.py +++ b/tests/test_inlinequeryhandler.py @@ -98,10 +98,10 @@ def callback_context(self, update, context): isinstance(update.inline_query, InlineQuery)) def callback_context_pattern(self, update, context): - if context.groups: - self.test_flag = context.groups == ('t', ' query') - if context.groupdict: - self.test_flag = context.groupdict == {'begin': 't', 'end': ' query'} + if context.match.groups(): + self.test_flag = context.match.groups() == ('t', ' query') + if context.match.groupdict(): + self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' query'} def test_basic(self, dp, inline_query): handler = InlineQueryHandler(self.callback_basic, use_context=False) diff --git a/tests/test_regexhandler.py b/tests/test_regexhandler.py index 1a14c3dc586..f2ced2097fc 100644 --- a/tests/test_regexhandler.py +++ b/tests/test_regexhandler.py @@ -91,10 +91,10 @@ def callback_context(self, update, context): isinstance(update.message, Message)) def callback_context_pattern(self, update, context): - if context.groups: - self.test_flag = context.groups == ('t', ' message') - if context.groupdict: - self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} + if context.match.groups(): + self.test_flag = context.match.groups() == ('t', ' message') + if context.match.groupdict(): + self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' message'} def test_basic(self, dp, message): handler = RegexHandler('.*', self.callback_basic, use_context=False) diff --git a/tests/test_stringcommandhandler.py b/tests/test_stringcommandhandler.py index f9b0ff9e07a..e02e7ae7ad5 100644 --- a/tests/test_stringcommandhandler.py +++ b/tests/test_stringcommandhandler.py @@ -90,13 +90,17 @@ def test_basic(self, dp): handler = StringCommandHandler('test', self.callback_basic, use_context=False) dp.add_handler(handler) - assert handler.check_update('/test') + check = handler.check_update('/test') + assert check is not None and check is not False dp.process_update('/test') assert self.test_flag - assert not handler.check_update('/nottest') - assert not handler.check_update('not /test in front') - assert handler.check_update('/test followed by text') + check = handler.check_update('/nottest') + assert check is None or check is False + check = handler.check_update('not /test in front') + assert check is None or check is False + check = handler.check_update('/test followed by text') + assert check is not None and check is not False def test_pass_args(self, dp): handler = StringCommandHandler('test', self.sch_callback_args, use_context=False, diff --git a/tests/test_stringregexhandler.py b/tests/test_stringregexhandler.py index 3d0c594d0bc..3dff8678cf8 100644 --- a/tests/test_stringregexhandler.py +++ b/tests/test_stringregexhandler.py @@ -82,10 +82,10 @@ def callback_context(self, update, context): isinstance(context.job_queue, JobQueue)) def callback_context_pattern(self, update, context): - if context.groups: - self.test_flag = context.groups == ('t', ' message') - if context.groupdict: - self.test_flag = context.groupdict == {'begin': 't', 'end': ' message'} + if context.match.groups(): + self.test_flag = context.match.groups() == ('t', ' message') + if context.match.groupdict(): + self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' message'} def test_basic(self, dp): handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic, From e87a70539a6fc4b6f2a27925edbb7296728c33da Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 16:06:48 +0200 Subject: [PATCH 19/32] Don't allow users to ignore errors without messing with the warning filters themselves --- telegram/ext/handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index fca25562709..397d949e7b2 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -79,7 +79,7 @@ def __init__(self, pass_job_queue=False, pass_user_data=False, pass_chat_data=False, - use_context=None): + use_context=False): self.callback = callback self.pass_update_queue = pass_update_queue self.pass_job_queue = pass_job_queue @@ -87,7 +87,7 @@ def __init__(self, self.pass_chat_data = pass_chat_data self.use_context = use_context - if use_context is None: + if not use_context: warnings.warn('You are currently not using context based handlers. This is being ' 'deprecated, and will soon not be possible. Please change your ' 'callback function signatures from (bot, update, others...) to (' From 397ab7758aa49a478d59f3f35affc48de3f7c3ea Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Sat, 5 May 2018 16:50:37 +0200 Subject: [PATCH 20/32] Ignore our own deprecation warnings when testing --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index ae23f5e89a3..1ff7a5cfbd7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,6 +24,7 @@ addopts = --no-success-flaky-report -rsxX filterwarnings = error ignore::DeprecationWarning + ignore::telegram.utils.deprecate.TelegramDeprecationWarning [coverage:run] branch = True From 46f2a26dc5bbdfc72e7ab283ca0cececdba56008 Mon Sep 17 00:00:00 2001 From: Eldinnie Date: Mon, 7 May 2018 17:47:32 +0200 Subject: [PATCH 21/32] Skipping deprecationwarning test on py2 --- tests/test_callbackqueryhandler.py | 2 +- tests/test_choseninlineresulthandler.py | 4 +++- tests/test_commandhandler.py | 2 +- tests/test_inlinequeryhandler.py | 2 +- tests/test_messagehandler.py | 2 +- tests/test_precheckoutqueryhandler.py | 4 +++- tests/test_regexhandler.py | 2 +- tests/test_shippingqueryhandler.py | 4 +++- tests/test_stringcommandhandler.py | 2 +- tests/test_stringregexhandler.py | 2 +- tests/test_typehandler.py | 2 +- 11 files changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/test_callbackqueryhandler.py b/tests/test_callbackqueryhandler.py index eef7cd787b1..d61d060e16e 100644 --- a/tests/test_callbackqueryhandler.py +++ b/tests/test_callbackqueryhandler.py @@ -200,7 +200,7 @@ def test_context(self, dp, callback_query): dp.process_update(callback_query) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): CallbackQueryHandler(self.callback_context) diff --git a/tests/test_choseninlineresulthandler.py b/tests/test_choseninlineresulthandler.py index 79a8536a9d4..5936ca3e055 100644 --- a/tests/test_choseninlineresulthandler.py +++ b/tests/test_choseninlineresulthandler.py @@ -16,6 +16,7 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +import sys from queue import Queue import pytest @@ -161,6 +162,7 @@ def test_context(self, dp, chosen_inline_result): dp.process_update(chosen_inline_result) assert self.test_flag - def test_non_context_deprecation(self, dp): + @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): ChosenInlineResultHandler(self.callback_context) diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index c80cdf247e5..b11a8e868e6 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -313,7 +313,7 @@ def test_context(self, dp, message): dp.process_update(Update(0, message)) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): CommandHandler('test', self.callback_context) diff --git a/tests/test_inlinequeryhandler.py b/tests/test_inlinequeryhandler.py index 690e0a0c94f..0bb6eb14fd3 100644 --- a/tests/test_inlinequeryhandler.py +++ b/tests/test_inlinequeryhandler.py @@ -200,7 +200,7 @@ def test_context(self, dp, inline_query): dp.process_update(inline_query) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): InlineQueryHandler(self.callback_context) diff --git a/tests/test_messagehandler.py b/tests/test_messagehandler.py index f87bff7cd72..e648631db81 100644 --- a/tests/test_messagehandler.py +++ b/tests/test_messagehandler.py @@ -230,6 +230,6 @@ def test_context(self, dp, message): dp.process_update(Update(0, edited_channel_post=message)) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): MessageHandler(None, self.callback_context) diff --git a/tests/test_precheckoutqueryhandler.py b/tests/test_precheckoutqueryhandler.py index e325980310c..20818b80f38 100644 --- a/tests/test_precheckoutqueryhandler.py +++ b/tests/test_precheckoutqueryhandler.py @@ -16,6 +16,7 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +import sys from queue import Queue import pytest @@ -163,6 +164,7 @@ def test_context(self, dp, pre_checkout_query): dp.process_update(pre_checkout_query) assert self.test_flag - def test_non_context_deprecation(self, dp): + @pytest.mark.skipif(sys.version_info == (2, 7), reason='pytest fails this for no reason') + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): PreCheckoutQueryHandler(self.callback_context) diff --git a/tests/test_regexhandler.py b/tests/test_regexhandler.py index f2ced2097fc..508ef82bae8 100644 --- a/tests/test_regexhandler.py +++ b/tests/test_regexhandler.py @@ -234,7 +234,7 @@ def test_context(self, dp, message): dp.process_update(Update(0, message=message)) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): RegexHandler('test', self.callback_context) diff --git a/tests/test_shippingqueryhandler.py b/tests/test_shippingqueryhandler.py index 564c715320f..5183b8180dc 100644 --- a/tests/test_shippingqueryhandler.py +++ b/tests/test_shippingqueryhandler.py @@ -16,6 +16,7 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +import sys from queue import Queue import pytest @@ -164,6 +165,7 @@ def test_context(self, dp, shiping_query): dp.process_update(shiping_query) assert self.test_flag - def test_non_context_deprecation(self, dp): + @pytest.mark.skipif(sys.version_info == (2, 7), reason='pytest fails this for no reason') + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): ShippingQueryHandler(self.callback_context) diff --git a/tests/test_stringcommandhandler.py b/tests/test_stringcommandhandler.py index e02e7ae7ad5..20f66e59dc0 100644 --- a/tests/test_stringcommandhandler.py +++ b/tests/test_stringcommandhandler.py @@ -152,7 +152,7 @@ def test_context(self, dp): dp.process_update('/test') assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): StringCommandHandler('test', self.callback_context) diff --git a/tests/test_stringregexhandler.py b/tests/test_stringregexhandler.py index 3dff8678cf8..bfb4156b962 100644 --- a/tests/test_stringregexhandler.py +++ b/tests/test_stringregexhandler.py @@ -152,7 +152,7 @@ def test_context(self, dp): dp.process_update('test message') assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): StringRegexHandler('test', self.callback_context) diff --git a/tests/test_typehandler.py b/tests/test_typehandler.py index 724e9ec7cc0..e389ed339f2 100644 --- a/tests/test_typehandler.py +++ b/tests/test_typehandler.py @@ -100,6 +100,6 @@ def test_context(self, dp): dp.process_update({'a': 1, 'b': 2}) assert self.test_flag - def test_non_context_deprecation(self, dp): + def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): TypeHandler(dict, self.callback_context) From fe27912fd0361c9f0ee6067f8b742f65654592d0 Mon Sep 17 00:00:00 2001 From: Eldinnie Date: Mon, 7 May 2018 17:53:08 +0200 Subject: [PATCH 22/32] Forgot some changes --- tests/test_precheckoutqueryhandler.py | 2 +- tests/test_shippingqueryhandler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_precheckoutqueryhandler.py b/tests/test_precheckoutqueryhandler.py index 20818b80f38..cedc307e399 100644 --- a/tests/test_precheckoutqueryhandler.py +++ b/tests/test_precheckoutqueryhandler.py @@ -164,7 +164,7 @@ def test_context(self, dp, pre_checkout_query): dp.process_update(pre_checkout_query) assert self.test_flag - @pytest.mark.skipif(sys.version_info == (2, 7), reason='pytest fails this for no reason') + @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): PreCheckoutQueryHandler(self.callback_context) diff --git a/tests/test_shippingqueryhandler.py b/tests/test_shippingqueryhandler.py index 5183b8180dc..82d39db049a 100644 --- a/tests/test_shippingqueryhandler.py +++ b/tests/test_shippingqueryhandler.py @@ -165,7 +165,7 @@ def test_context(self, dp, shiping_query): dp.process_update(shiping_query) assert self.test_flag - @pytest.mark.skipif(sys.version_info == (2, 7), reason='pytest fails this for no reason') + @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') def test_non_context_deprecation(self): with pytest.warns(TelegramDeprecationWarning): ShippingQueryHandler(self.callback_context) From 0f44eed49efc8a93db69940d0aa8c8074bab7405 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Mon, 7 May 2018 22:49:38 +0300 Subject: [PATCH 23/32] Handler: Improved documentation and text of deprecation warnings --- telegram/ext/handler.py | 64 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 397d949e7b2..c0d00b1abf2 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -30,11 +30,11 @@ class Handler(object): callback (:obj:`callable`): The callback function for this handler. pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. @@ -44,13 +44,16 @@ class Handler(object): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + ``def callback(update: Update, context: HandlerContext)`` + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -67,12 +70,11 @@ class Handler(object): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ - def __init__(self, callback, pass_update_queue=False, @@ -87,16 +89,13 @@ def __init__(self, self.pass_chat_data = pass_chat_data self.use_context = use_context + if use_context and ( + pass_update_queue or pass_job_queue or pass_user_data or pass_chat_data): + raise ValueError('Mix of Context Based Handler API and old Handler API is not allowed') + if not use_context: - warnings.warn('You are currently not using context based handlers. This is being ' - 'deprecated, and will soon not be possible. Please change your ' - 'callback function signatures from (bot, update, others...) to (' - 'update, context), and create your handlers using use_context=True ' - 'instead of setting any pass_ parameters. You can set ' - 'use_context=False to turn this warning off. Please see ' - 'https://git.io/vpVe8 for more info.', - TelegramDeprecationWarning, - stacklevel=3) + warnings.warn('Old Handler API is deprecated - see https://git.io/vpVe8 for details', + TelegramDeprecationWarning, stacklevel=3) def check_update(self, update): """ @@ -117,18 +116,17 @@ def check_update(self, update): def handle_update(self, update, dispatcher, check_result): """ This method is called if it was determined that an update should indeed - be handled by this instance. Calls ``self.callback(dispatcher.bot, update)``, - along with optional arguments. To work with the ``ConversationHandler``, this method + be handled by this instance. Calls :attr:`self.callback` along with its respectful + arguments. To work with the :class:`telegram.ext.ConversationHandler`, this method returns the value returned from ``self.callback``. Note that it can be overridden if needed by the subclassing handler. Args: update (:obj:`str` | :class:`telegram.Update`): The update to be handled. - dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher to collect optional args. - check_result: The result from check_update + dispatcher (:class:`telegram.ext.Dispatcher`): The calling dispatcher. + check_result: The result from :attr:`check_update`. """ - if self.use_context: context = HandlerContext(update, dispatcher) self.collect_additional_context(context, update, dispatcher, check_result) @@ -138,26 +136,30 @@ def handle_update(self, update, dispatcher, check_result): return self.callback(dispatcher.bot, update, **optional_args) def collect_additional_context(self, context, update, dispatcher, check_result): - """Prepares additional arguments for the context. Override if handler needs. + """Prepares additional arguments for the context. Override if needed. Args: - context (:class:`telegram.ext.HandlerContext`): The context. + context (:class:`telegram.ext.HandlerContext`): The context object. update (:class:`telegram.Update`): The update to gather chat/user id from. - dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. - check_result: The result from check_update + dispatcher (:class:`telegram.ext.Dispatcher`): The calling dispatcher. + check_result: The result (return value) from :attr:`check_update`. + """ pass def collect_optional_args(self, dispatcher, update=None, check_result=None): - """Prepares the optional arguments. If the handler has additional optional args, + """ + Prepares the optional arguments. If the handler has additional optional args, it should subclass this method, but remember to call this super method. - Usage of this method is being replaced by new context aware handlers. Please see + + DEPRECATED: This method is being replaced by new Context Based Handlers. Please see https://git.io/vpVe8 for more info. Args: dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. update (:class:`telegram.Update`): The update to gather chat/user id from. check_result: The result from check_update + """ optional_args = dict() From b54f7e52c722aeea818f3ff6ab316d217c23e759 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Mon, 7 May 2018 22:50:15 +0300 Subject: [PATCH 24/32] HandlerContext: Keep only dispatcher and use properties; improved doc --- telegram/ext/handler.py | 60 +++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index c0d00b1abf2..4456e7d523e 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -181,18 +181,9 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): class HandlerContext(object): - """ - This object represents additional data passed along with an update from telegram. - To use it set :attr:`use_context` to ``True`` when creating your handlers, and use the - following signature for your callback functions ``def callbackname(update, context):``. + """This is a context object passed to the callback called by :class:`telegram.ext.Handler`. Attributes: - bot (:class:`telegram.Bot`): The bot associated with this context. - job_queue (:class:`telegram.ext.JobQueue`): The JobQueue created by the - :class:`telegram.ext.Updater` which can be used to schedule new jobs. - update_queue (:class:`queue.Queue`): The ``Queue`` instance used by the - :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` - which contains new updates and can be used to insert updates. chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each update from the same chat it will be the same ``dict``. user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each @@ -201,10 +192,10 @@ class HandlerContext(object): regex-supported handler, this will contain the object returned from ``re.match( pattern, string)``. args (List[:obj:`str`], optional): Arguments passed to a command if the associated update - originated from a :class:`telegram.ext.CommandHandler` or a - :class:`telegram.ext.StringCommandHandler`. It will contain a list of strings, - which is the text following the command split on single or consecutive whitespace - characters. + is handled by :class:`telegram.ext.CommandHandler` or + :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the text + after the command, using any whitespace string as a delimiter. + """ chat_data = None @@ -213,10 +204,14 @@ class HandlerContext(object): match = None def __init__(self, update, dispatcher): + """ + Args: + update (:class:`telegram.Update`): + dispatcher (:class:`telegram.ext.Dispatcher`): + + """ self.update = update - self.bot = dispatcher.bot - self.job_queue = dispatcher.job_queue - self.update_queue = dispatcher.update_queue + self._dispatcher = dispatcher if update is not None and isinstance(update, Update): chat = update.effective_chat @@ -226,3 +221,34 @@ def __init__(self, update, dispatcher): self.chat_data = dispatcher.chat_data[chat.id] if user: self.user_data = dispatcher.user_data[user.id] + + @property + def bot(self): + """ + Returns: + :class:`telegram.Bot`: The bot associated with this context. + + """ + return self._dispatcher.bot + + @property + def job_queue(self): + """ + Returns: + :class:`telegram.ext.JobQueue`: The ``JobQueue`` used by the + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` + associated with this :class:`HandlerContext`. + + """ + return self._dispatcher.job_queue + + @property + def update_queue(self): + """ + Returns: + :class:`queue.Queue`: The ``Queue`` instance used by the + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` + associated with this :class:`HandlerContext`. + + """ + return self._dispatcher.update_queue From f26bf62f3bed270d2d8b9ccd6d4cc5b07734a784 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Tue, 8 May 2018 01:08:56 +0300 Subject: [PATCH 25/32] Complete fixing the documentation. - Fixes per Eldinnie's comments. - Fixes per warnings when running sphinx. --- telegram/ext/callbackqueryhandler.py | 37 +++++++++++--------- telegram/ext/choseninlineresulthandler.py | 30 ++++++++++------- telegram/ext/commandhandler.py | 36 +++++++++++--------- telegram/ext/conversationhandler.py | 8 ++--- telegram/ext/handler.py | 41 ++++++++++------------- telegram/ext/inlinequeryhandler.py | 38 ++++++++++++--------- telegram/ext/messagehandler.py | 34 +++++++++++-------- telegram/ext/precheckoutqueryhandler.py | 30 ++++++++++------- telegram/ext/regexhandler.py | 36 +++++++++++--------- telegram/ext/shippingqueryhandler.py | 30 ++++++++++------- telegram/ext/stringcommandhandler.py | 29 +++++++++------- telegram/ext/stringregexhandler.py | 29 +++++++++------- telegram/ext/typehandler.py | 29 +++++++++------- 13 files changed, 231 insertions(+), 176 deletions(-) diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index 5ea0bc330b2..afa40e97f37 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -33,21 +33,21 @@ class CallbackQueryHandler(Handler): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. pattern (:obj:`str` | `Pattern`): Optional. Regex pattern to test :attr:`telegram.CallbackQuery.data` against. - pass_groups (:obj:`bool`): Optional. Determines whether ``groups`` will be passed to the + pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the callback function. - pass_groupdict (:obj:`bool`): Optional. Determines whether ``groupdict``. will be passed to + pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -55,13 +55,19 @@ class CallbackQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -89,12 +95,11 @@ class CallbackQueryHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ - def __init__(self, callback, pass_update_queue=False, @@ -104,7 +109,7 @@ def __init__(self, pass_groupdict=False, pass_user_data=False, pass_chat_data=False, - use_context=None): + use_context=False): super(CallbackQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index a4bf79bef83..aece6dbab62 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -27,15 +27,15 @@ class ChosenInlineResultHandler(Handler): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -43,13 +43,19 @@ class ChosenInlineResultHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -66,9 +72,9 @@ class ChosenInlineResultHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 51d45d81b07..3ce4378f54a 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -35,19 +35,19 @@ class CommandHandler(Handler): callback (:obj:`callable`): The callback function for this handler. filters (:class:`telegram.ext.BaseFilter`): Optional. Only allow updates with these Filters. - allow_edited (:obj:`bool`): Optional. Determines Whether the handler should also accept + allow_edited (:obj:`bool`): Determines Whether the handler should also accept edited messages. - pass_args (:obj:`bool`): Optional. Determines whether the handler should be passed + pass_args (:obj:`bool`): Determines whether the handler should be passed ``args``. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -55,15 +55,21 @@ class CommandHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: command (:obj:`str` | List[:obj:`str`]): The command or list of commands this handler should listen for. - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. filters (:class:`telegram.ext.BaseFilter`, optional): A filter inheriting from :class:`telegram.ext.filters.BaseFilter`. Standard filters can be found in :class:`telegram.ext.filters.Filters`. Filters can be combined using bitwise @@ -91,9 +97,9 @@ class CommandHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ @@ -107,7 +113,7 @@ def __init__(self, pass_job_queue=False, pass_user_data=False, pass_chat_data=False, - use_context=None): + use_context=False): super(CommandHandler, self).__init__( callback, pass_update_queue=pass_update_queue, diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py index 2bbad640fe7..87864bcfcab 100644 --- a/telegram/ext/conversationhandler.py +++ b/telegram/ext/conversationhandler.py @@ -66,15 +66,15 @@ class ConversationHandler(Handler): fallbacks (List[:class:`telegram.ext.Handler`]): A list of handlers that might be used if the user is in a conversation, but every handler for their current state returned ``False`` on :attr:`check_update`. - allow_reentry (:obj:`bool`): Optional. Determines if a user can restart a conversation with + allow_reentry (:obj:`bool`): Determines if a user can restart a conversation with an entry point. run_async_timeout (:obj:`float`): Optional. The time-out for ``run_async`` decorated Handlers. timed_out_behavior (List[:class:`telegram.ext.Handler`]): Optional. A list of handlers that might be used if the wait for ``run_async`` timed out. - per_chat (:obj:`bool`): Optional. If the conversationkey should contain the Chat's ID. - per_user (:obj:`bool`): Optional. If the conversationkey should contain the User's ID. - per_message (:obj:`bool`): Optional. If the conversationkey should contain the Message's + per_chat (:obj:`bool`): If the conversationkey should contain the Chat's ID. + per_user (:obj:`bool`): If the conversationkey should contain the User's ID. + per_message (:obj:`bool`): If the conversationkey should contain the Message's ID. conversation_timeout (:obj:`float`|:obj:`datetime.timedelta`): Optional. When this handler is inactive more than this timeout (in seconds), it will be automatically ended. If diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 4456e7d523e..8b179ea5441 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -36,7 +36,7 @@ class Handler(object): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -44,6 +44,7 @@ class Handler(object): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. @@ -51,7 +52,9 @@ class Handler(object): callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + + ``def callback(update: Update, context: HandlerContext)`` + The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called @@ -188,21 +191,15 @@ class HandlerContext(object): update from the same chat it will be the same ``dict``. user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each update from the same user it will be the same ``dict``. - match (:obj:`_sre.SRE_Match`, optional): If the associated update originated from a - regex-supported handler, this will contain the object returned from ``re.match( - pattern, string)``. + match (:obj:`re match object`, optional): If the associated update originated from a + regex-supported handler, this will contain the object returned from + ``re.match(pattern, string)``. args (List[:obj:`str`], optional): Arguments passed to a command if the associated update is handled by :class:`telegram.ext.CommandHandler` or :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the text after the command, using any whitespace string as a delimiter. """ - - chat_data = None - user_data = None - args = None - match = None - def __init__(self, update, dispatcher): """ Args: @@ -212,6 +209,10 @@ def __init__(self, update, dispatcher): """ self.update = update self._dispatcher = dispatcher + self.chat_data = None + self.user_data = None + self.args = None + self.match = None if update is not None and isinstance(update, Update): chat = update.effective_chat @@ -224,20 +225,15 @@ def __init__(self, update, dispatcher): @property def bot(self): - """ - Returns: - :class:`telegram.Bot`: The bot associated with this context. - - """ + """:class:`telegram.Bot`: The bot associated with this context.""" return self._dispatcher.bot @property def job_queue(self): """ - Returns: - :class:`telegram.ext.JobQueue`: The ``JobQueue`` used by the - :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` - associated with this :class:`HandlerContext`. + :class:`telegram.ext.JobQueue`: The ``JobQueue`` used by the + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` + associated with this context. """ return self._dispatcher.job_queue @@ -245,10 +241,9 @@ def job_queue(self): @property def update_queue(self): """ - Returns: - :class:`queue.Queue`: The ``Queue`` instance used by the + :class:`queue.Queue`: The ``Queue`` instance used by the :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` - associated with this :class:`HandlerContext`. + associated with this context. """ return self._dispatcher.update_queue diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 9777e1ede1a..5665858495e 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -32,21 +32,21 @@ class InlineQueryHandler(Handler): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. pattern (:obj:`str` | :obj:`Pattern`): Optional. Regex pattern to test :attr:`telegram.InlineQuery.query` against. - pass_groups (:obj:`bool`): Optional. Determines whether ``groups`` will be passed to the + pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the callback function. - pass_groupdict (:obj:`bool`): Optional. Determines whether ``groupdict``. will be passed to + pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -54,13 +54,19 @@ class InlineQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -88,9 +94,10 @@ class InlineQueryHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. + """ def __init__(self, @@ -102,7 +109,7 @@ def __init__(self, pass_groupdict=False, pass_user_data=False, pass_chat_data=False, - use_context=None): + use_context=False): super(InlineQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, @@ -127,6 +134,7 @@ def check_update(self, update): Returns: :obj:`bool` + """ if isinstance(update, Update) and update.inline_query: diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 1664957752d..19c2bcfce8e 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -31,23 +31,23 @@ class MessageHandler(Handler): filters (:obj:`Filter`): Only allow updates with these Filters. See :mod:`telegram.ext.filters` for a full list of all available filters. callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - message_updates (:obj:`bool`): Optional. Should "normal" message updates be handled? + message_updates (:obj:`bool`): Should "normal" message updates be handled? Default is ``True``. - channel_post_updates (:obj:`bool`): Optional. Should channel posts updates be handled? + channel_post_updates (:obj:`bool`): Should channel posts updates be handled? Default is ``True``. - edited_updates (:obj:`bool`): Optional. Should "edited" message updates be handled? + edited_updates (:obj:`bool`): Should "edited" message updates be handled? Default is ``False``. - allow_edited (:obj:`bool`): Optional. If the handler should also accept edited messages. + allow_edited (:obj:`bool`): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -55,7 +55,8 @@ class MessageHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: @@ -63,9 +64,14 @@ class MessageHandler(Handler): :class:`telegram.ext.filters.BaseFilter`. Standard filters can be found in :class:`telegram.ext.filters.Filters`. Filters can be combined using bitwise operators (& for and, | for or, ~ for not). - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -110,7 +116,7 @@ def __init__(self, message_updates=True, channel_post_updates=True, edited_updates=False, - use_context=None): + use_context=False): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index 90b3b4860ab..f0e83770637 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -27,15 +27,15 @@ class PreCheckoutQueryHandler(Handler): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -43,13 +43,19 @@ class PreCheckoutQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` DEPRECATED: Please switch to context based handlers. @@ -66,9 +72,9 @@ class PreCheckoutQueryHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 9fb77f2cd48..28cbd1767c6 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -38,19 +38,19 @@ class RegexHandler(Handler): Attributes: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. callback (:obj:`callable`): The callback function for this handler. - pass_groups (:obj:`bool`): Optional. Determines whether ``groups`` will be passed to the + pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the callback function. - pass_groupdict (:obj:`bool`): Optional. Determines whether ``groupdict``. will be passed to + pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to the callback function. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -58,14 +58,20 @@ class RegexHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` @@ -98,9 +104,9 @@ class RegexHandler(Handler): is ``False``. allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. Raises: ValueError @@ -120,7 +126,7 @@ def __init__(self, message_updates=True, channel_post_updates=False, edited_updates=False, - use_context=None): + use_context=False): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index b005cc05fae..1618dc4d67c 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -27,15 +27,15 @@ class ShippingQueryHandler(Handler): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - pass_user_data (:obj:`bool`): Optional. Determines whether ``user_data`` will be passed to + pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to the callback function. - pass_chat_data (:obj:`bool`): Optional. Determines whether ``chat_data`` will be passed to + pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Note: @@ -43,13 +43,19 @@ class ShippingQueryHandler(Handler): can use to keep any data in will be sent to the :attr:`callback` function.. Related to either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is deprecated, please switch to context based handlers. See + + Note that this is DEPRECATED, and you should use Context Based Handlers. See https://git.io/vpVe8 for more info. Args: - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` @@ -66,9 +72,9 @@ class ShippingQueryHandler(Handler): pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 3aaa1601933..b74a781e999 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -33,20 +33,24 @@ class StringCommandHandler(Handler): Attributes: command (:obj:`str`): The command this handler should listen for. callback (:obj:`callable`): The callback function for this handler. - pass_args (:obj:`bool`): Optional. Determines whether the handler should be passed + pass_args (:obj:`bool`): Determines whether the handler should be passed ``args``. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Args: - command (:obj:`str`): The command this handler should listen for. - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that a command should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_args (:obj:`bool`, optional): Determines whether the handler should be passed the arguments passed to the command as a keyword argument called ``args``. It will contain a list of strings, which is the text following the command split on single or @@ -62,9 +66,9 @@ class StringCommandHandler(Handler): class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ @@ -74,7 +78,7 @@ def __init__(self, pass_args=False, pass_update_queue=False, pass_job_queue=False, - use_context=None): + use_context=False): super(StringCommandHandler, self).__init__( callback, pass_update_queue=pass_update_queue, @@ -93,7 +97,6 @@ def check_update(self, update): :obj:`bool` """ - if isinstance(update, string_types) and update.startswith('/'): args = update[1:].split(' ') if args[0] == self.command: diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index 94e606d9f97..75aed3a89f7 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -38,22 +38,27 @@ class StringRegexHandler(Handler): Attributes: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. callback (:obj:`callable`): The callback function for this handler. - pass_groups (:obj:`bool`): Optional. Determines whether ``groups`` will be passed to the + pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the callback function. - pass_groupdict (:obj:`bool`): Optional. Determines whether ``groupdict``. will be passed to + pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to the callback function. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` @@ -72,9 +77,9 @@ class StringRegexHandler(Handler): :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ @@ -85,7 +90,7 @@ def __init__(self, pass_groupdict=False, pass_update_queue=False, pass_job_queue=False, - use_context=None): + use_context=False): super(StringRegexHandler, self).__init__( callback, pass_update_queue=pass_update_queue, diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index f9f4f82a81d..a348d01dca7 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -27,21 +27,25 @@ class TypeHandler(Handler): Attributes: type (:obj:`type`): The ``type`` of updates this handler should process. callback (:obj:`callable`): The callback function for this handler. - strict (:obj:`bool`): Optional. Use ``type`` instead of ``isinstance``. - Default is ``False`` - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + strict (:obj:`bool`): Use ``type`` instead of ``isinstance``. Default is ``False``. + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. - pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to + pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Optional. Determines whether all `pass_` arguments will be + use_context (:obj:`bool`): Determines whether all `pass_` arguments will be ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. Args: type (:obj:`type`): The ``type`` of updates this handler should process, as determined by ``isinstance`` - callback (:obj:`callable`): A function that takes ``bot, update`` as positional arguments. - It will be called when the :attr:`check_update` has determined that an update should be - processed by this handler. + callback (:obj:`callable`): The callback function for this handler. Will be called when + :attr:`check_update` has determined that an update should be processed by this handler. + Callback signature for context based API: + + ``def callback(update: Update, context: HandlerContext)`` + + The return value of the callback is usually ignored except for the special case of + :class:`telegram.ext.ConversationHandler`. strict (:obj:`bool`, optional): Use ``type`` instead of ``isinstance``. Default is ``False`` pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called @@ -54,9 +58,9 @@ class TypeHandler(Handler): :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ @@ -66,7 +70,7 @@ def __init__(self, strict=False, pass_update_queue=False, pass_job_queue=False, - use_context=None): + use_context=False): super(TypeHandler, self).__init__( callback, pass_update_queue=pass_update_queue, @@ -85,7 +89,6 @@ def check_update(self, update): :obj:`bool` """ - if not self.strict: return isinstance(update, self.type) else: From 8184902ee388c79f9c47ab6d35c84f1e9cd8f9d6 Mon Sep 17 00:00:00 2001 From: Pieter Schutz Date: Tue, 8 May 2018 11:03:16 +0200 Subject: [PATCH 26/32] Some small doc fixes (interlinks and optionals) --- telegram/ext/callbackqueryhandler.py | 3 ++- telegram/ext/choseninlineresulthandler.py | 3 ++- telegram/ext/commandhandler.py | 3 ++- telegram/ext/handler.py | 7 ++++--- telegram/ext/inlinequeryhandler.py | 3 ++- telegram/ext/messagehandler.py | 7 ++++--- telegram/ext/precheckoutqueryhandler.py | 3 ++- telegram/ext/regexhandler.py | 3 ++- telegram/ext/shippingqueryhandler.py | 3 ++- telegram/ext/stringcommandhandler.py | 3 ++- telegram/ext/stringregexhandler.py | 3 ++- telegram/ext/typehandler.py | 3 ++- 12 files changed, 28 insertions(+), 16 deletions(-) diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index afa40e97f37..0d36b7b23ea 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -48,7 +48,8 @@ class CallbackQueryHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index aece6dbab62..f5e831dbeae 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -36,7 +36,8 @@ class ChosenInlineResultHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 3ce4378f54a..817a6de59d0 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -48,7 +48,8 @@ class CommandHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 8b179ea5441..5642b17e590 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -28,7 +28,7 @@ class Handler(object): Attributes: callback (:obj:`callable`): The callback function for this handler. - pass_update_queue (:obj:`bool`): Optional. Determines whether ``update_queue`` will be + pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be passed to the callback function. pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. @@ -37,7 +37,8 @@ class Handler(object): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -242,7 +243,7 @@ def job_queue(self): def update_queue(self): """ :class:`queue.Queue`: The ``Queue`` instance used by the - :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegram.ext.Updater` associated with this context. """ diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 5665858495e..8a24686faea 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -47,7 +47,8 @@ class InlineQueryHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 19c2bcfce8e..2b6cbd6dd7e 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -48,7 +48,8 @@ class MessageHandler(Handler): allow_edited (:obj:`bool`): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -97,8 +98,8 @@ class MessageHandler(Handler): allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. - Defaults to ``False`` for while the old `pass_` method is in deprecation. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Raises: ValueError diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index f0e83770637..b20a3100da1 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -36,7 +36,8 @@ class PreCheckoutQueryHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 28cbd1767c6..5924723ebfb 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -51,7 +51,8 @@ class RegexHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index 1618dc4d67c..d9ec190c9c4 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -36,7 +36,8 @@ class ShippingQueryHandler(Handler): pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index b74a781e999..80691280d5b 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -40,7 +40,8 @@ class StringCommandHandler(Handler): pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index 75aed3a89f7..0d12837d7f5 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -47,7 +47,8 @@ class StringRegexHandler(Handler): pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index a348d01dca7..cd2584718c0 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -33,7 +33,8 @@ class TypeHandler(Handler): pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.Context` object to the callback. + ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the + callback. Args: type (:obj:`type`): The ``type`` of updates this handler should process, as From 5dc53a52b90d6781a899aea271969256e9e494ea Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 10 May 2018 11:40:47 +0200 Subject: [PATCH 27/32] Change add_error_handler to use HandlerContext too --- telegram/ext/dispatcher.py | 43 ++++++++++++++++++++++++++++++-------- telegram/ext/handler.py | 10 +++++++++ tests/test_dispatcher.py | 27 ++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/telegram/ext/dispatcher.py b/telegram/ext/dispatcher.py index 2f3790ed961..6e061abeaba 100644 --- a/telegram/ext/dispatcher.py +++ b/telegram/ext/dispatcher.py @@ -19,6 +19,7 @@ """This module contains the Dispatcher class.""" import logging +import warnings import weakref from functools import wraps from threading import Thread, Lock, Event, current_thread, BoundedSemaphore @@ -31,7 +32,8 @@ from future.builtins import range from telegram import TelegramError -from telegram.ext.handler import Handler +from telegram.ext.handler import Handler, HandlerContext +from telegram.utils.deprecate import TelegramDeprecationWarning from telegram.utils.promise import Promise logging.getLogger(__name__).addHandler(logging.NullHandler()) @@ -353,15 +355,27 @@ def remove_handler(self, handler, group=DEFAULT_GROUP): del self.handlers[group] self.groups.remove(group) - def add_error_handler(self, callback): + def add_error_handler(self, callback, use_context=False): """Registers an error handler in the Dispatcher. Args: - callback (:obj:`callable`): A function that takes ``Bot, Update, TelegramError`` as - arguments. + callback (:obj:`callable`): The callback function for this error handler. Will be + called when an error is raised Callback signature for context based API: + ``def callback(update: Update, context: HandlerContext)`` + + The error that happened will be present in context.error. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback + API. During the deprecation period of the old API the default is ``False``. + **New users**: set this to ``True``. + + Note: + See https://git.io/vpVe8 for more info about switching to context based API. """ - self.error_handlers.append(callback) + if not use_context: + warnings.warn('Old Handler API is deprecated - see https://git.io/vpVe8 for details', + TelegramDeprecationWarning, stacklevel=2) + self.error_handlers.append((callback, use_context)) def remove_error_handler(self, callback): """Removes an error handler. @@ -370,8 +384,16 @@ def remove_error_handler(self, callback): callback (:obj:`callable`): The error handler to remove. """ - if callback in self.error_handlers: - self.error_handlers.remove(callback) + try: + self.error_handlers.remove((callback, True)) + return + except ValueError: + pass + try: + self.error_handlers.remove((callback, False)) + return + except ValueError: + pass def dispatch_error(self, update, error): """Dispatches an error. @@ -382,8 +404,11 @@ def dispatch_error(self, update, error): """ if self.error_handlers: - for callback in self.error_handlers: - callback(self.bot, update, error) + for callback, use_context in self.error_handlers: + if use_context: + callback(update, HandlerContext.from_error(update, error, self)) + else: + callback(self.bot, update, error) else: self.logger.exception( diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 5642b17e590..093aad6ed55 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -199,6 +199,9 @@ class HandlerContext(object): is handled by :class:`telegram.ext.CommandHandler` or :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the text after the command, using any whitespace string as a delimiter. + error (:class:`telegram.TelegramError`, optional): The Telegram error that was raised. + Only present when passed to a error handler registered with + :attr:`telegram.ext.Dispatcher.add_error_handler`. """ def __init__(self, update, dispatcher): @@ -214,6 +217,7 @@ def __init__(self, update, dispatcher): self.user_data = None self.args = None self.match = None + self.error = None if update is not None and isinstance(update, Update): chat = update.effective_chat @@ -224,6 +228,12 @@ def __init__(self, update, dispatcher): if user: self.user_data = dispatcher.user_data[user.id] + @classmethod + def from_error(cls, update, error, dispatcher): + context = cls(update, dispatcher) + context.error = error + return context + @property def bot(self): """:class:`telegram.Bot`: The bot associated with this context.""" diff --git a/tests/test_dispatcher.py b/tests/test_dispatcher.py index 6dc6b236f4c..90e5fab963e 100644 --- a/tests/test_dispatcher.py +++ b/tests/test_dispatcher.py @@ -16,15 +16,17 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +import sys from queue import Queue from threading import current_thread from time import sleep import pytest -from telegram import TelegramError, Message, User, Chat, Update -from telegram.ext import MessageHandler, Filters, CommandHandler +from telegram import TelegramError, Message, User, Chat, Update, Bot +from telegram.ext import MessageHandler, Filters, CommandHandler, HandlerContext, JobQueue from telegram.ext.dispatcher import run_async, Dispatcher, DispatcherHandlerStop +from telegram.utils.deprecate import TelegramDeprecationWarning from tests.conftest import create_dp @@ -67,6 +69,14 @@ def callback_if_not_update_queue(self, bot, update, update_queue=None): if update_queue is not None: self.received = update.message + def callback_context(self, update, context): + if (isinstance(context, HandlerContext) and + isinstance(context.bot, Bot) and + isinstance(context.update_queue, Queue) and + isinstance(context.job_queue, JobQueue) and + isinstance(context.error, TelegramError)): + self.received = context.error.message + def test_error_handler(self, dp): dp.add_error_handler(self.error_handler) error = TelegramError('Unauthorized.') @@ -316,3 +326,16 @@ def error(b, u, e): dp.process_update(update) assert passed == ['start1', 'error', err] assert passed[2] is err + + def test_context(self, dp): + dp.add_error_handler(self.callback_context, True) + + error = TelegramError('Unauthorized.') + dp.update_queue.put(error) + sleep(.1) + assert self.received == 'Unauthorized.' + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') + def test_non_context_deprecation(self, dp): + with pytest.warns(TelegramDeprecationWarning): + dp.add_error_handler(self.callback_context) From eeb28167da28cb86e2d38d6a0a198f378cd49f69 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 10 May 2018 17:46:41 +0200 Subject: [PATCH 28/32] More context based changes Context Based Handlers -> Context Based Callbacks No longer use_context args on every single Handler Instead set dispatcher/updater .use_context=True to use Works with - Handler callbacks - Error handler callbacks - Job callbacks Change examples to context based callbacks so new users are not confused Rename and move the context object from Handlers.HandlerContext to CallbackContext, since it doesn't only apply to handlers anymore. Fix tests by adding a new fixture `cpd` which is a dispatcher with use_context=True --- CHANGES.rst | 16 ++- docs/source/telegram.ext.callbackcontext.rst | 5 + docs/source/telegram.ext.handlercontext.rst | 6 - docs/source/telegram.ext.rst | 2 +- examples/conversationbot.py | 32 ++--- examples/conversationbot2.py | 24 ++-- examples/echobot2.py | 19 +-- examples/inlinebot.py | 19 +-- examples/inlinekeyboard.py | 19 +-- examples/paymentbot.py | 51 ++++---- examples/timerbot.py | 35 +++--- telegram/ext/__init__.py | 5 +- telegram/ext/callbackcontext.py | 112 +++++++++++++++++ telegram/ext/callbackqueryhandler.py | 31 ++--- telegram/ext/choseninlineresulthandler.py | 20 ++- telegram/ext/commandhandler.py | 28 ++--- telegram/ext/dispatcher.py | 51 ++++---- telegram/ext/handler.py | 124 +++---------------- telegram/ext/inlinequeryhandler.py | 27 ++-- telegram/ext/jobqueue.py | 22 ++-- telegram/ext/messagehandler.py | 26 ++-- telegram/ext/precheckoutqueryhandler.py | 20 ++- telegram/ext/regexhandler.py | 30 ++--- telegram/ext/shippingqueryhandler.py | 20 ++- telegram/ext/stringcommandhandler.py | 20 +-- telegram/ext/stringregexhandler.py | 22 ++-- telegram/ext/typehandler.py | 18 +-- telegram/ext/updater.py | 13 +- tests/conftest.py | 10 +- tests/test_callbackqueryhandler.py | 57 ++++----- tests/test_choseninlineresulthandler.py | 35 +++--- tests/test_commandhandler.py | 61 +++++---- tests/test_dispatcher.py | 13 +- tests/test_inlinequeryhandler.py | 57 ++++----- tests/test_messagehandler.py | 51 ++++---- tests/test_precheckoutqueryhandler.py | 35 +++--- tests/test_regexhandler.py | 65 +++++----- tests/test_shippingqueryhandler.py | 35 +++--- tests/test_stringcommandhandler.py | 39 +++--- tests/test_stringregexhandler.py | 50 ++++---- tests/test_typehandler.py | 27 ++-- 41 files changed, 634 insertions(+), 718 deletions(-) create mode 100644 docs/source/telegram.ext.callbackcontext.rst delete mode 100644 docs/source/telegram.ext.handlercontext.rst create mode 100644 telegram/ext/callbackcontext.py diff --git a/CHANGES.rst b/CHANGES.rst index 971d6ea5fce..2536849f5e3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,13 +4,21 @@ Changes **2018-??-??** *Released 11.0.0* -Handler overhaul: +Context based callbacks: +See https://git.io/vp113 for help. - Use of `pass_` in handlers is deprecated. -- Instead use `use_context=True` and change callback from (bot, update, others...) to (update, context) See https://git.io/vpVe8 for help. -- Handlers should be faster due to deduped logic. For those with their own handlers subclass telegram.ext.Handler, this is backwards incompatible. -- Remove the last CamelCase CheckUpdate methods from the handlers we missed earlier. +- Instead use `use_context=True` on `Updater` or `Dispatcher` and change callback from (bot, update, others...) to (update, context). +- This also applies to error handlers `Dispatcher.add_error_handler` and JobQueue jobs (change (bot, job) to (context) here). +- For users with custom handlers subclassing Handler, this is mostly backwards compatible, but to use the new context based callbacks you need to implement the new collect_additional_context method. + +Other: +- Handlers should be faster due to deduped logic. + +Other removals: - Remove the ability to use filter lists in handlers. +- Remove the last CamelCase CheckUpdate methods from the handlers we missed earlier. + **2018-05-02** *Released 10.1.0* diff --git a/docs/source/telegram.ext.callbackcontext.rst b/docs/source/telegram.ext.callbackcontext.rst new file mode 100644 index 00000000000..36487931805 --- /dev/null +++ b/docs/source/telegram.ext.callbackcontext.rst @@ -0,0 +1,5 @@ +telegram.ext.CallbackContext +============================ + +.. autoclass:: telegram.ext.CallbackContext + :members: diff --git a/docs/source/telegram.ext.handlercontext.rst b/docs/source/telegram.ext.handlercontext.rst deleted file mode 100644 index 33daee780be..00000000000 --- a/docs/source/telegram.ext.handlercontext.rst +++ /dev/null @@ -1,6 +0,0 @@ -telegram.ext.HandlerContext -=========================== - -.. autoclass:: telegram.ext.HandlerContext - :members: - :undoc-members: diff --git a/docs/source/telegram.ext.rst b/docs/source/telegram.ext.rst index 1e1b0acad4f..09647a1bdd6 100644 --- a/docs/source/telegram.ext.rst +++ b/docs/source/telegram.ext.rst @@ -10,7 +10,7 @@ telegram.ext package telegram.ext.jobqueue telegram.ext.messagequeue telegram.ext.delayqueue - telegram.ext.handlercontext + telegram.ext.callbackcontext Handlers -------- diff --git a/examples/conversationbot.py b/examples/conversationbot.py index 06412ca354f..70f7f1cb0a3 100644 --- a/examples/conversationbot.py +++ b/examples/conversationbot.py @@ -17,12 +17,12 @@ bot. """ +import logging + from telegram import (ReplyKeyboardMarkup, ReplyKeyboardRemove) from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler, ConversationHandler) -import logging - # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) @@ -32,7 +32,7 @@ GENDER, PHOTO, LOCATION, BIO = range(4) -def start(bot, update): +def start(update, context): reply_keyboard = [['Boy', 'Girl', 'Other']] update.message.reply_text( @@ -44,7 +44,7 @@ def start(bot, update): return GENDER -def gender(bot, update): +def gender(update, context): user = update.message.from_user logger.info("Gender of %s: %s", user.first_name, update.message.text) update.message.reply_text('I see! Please send me a photo of yourself, ' @@ -54,9 +54,9 @@ def gender(bot, update): return PHOTO -def photo(bot, update): +def photo(update, context): user = update.message.from_user - photo_file = bot.get_file(update.message.photo[-1].file_id) + photo_file = update.message.photo[-1].get_file() photo_file.download('user_photo.jpg') logger.info("Photo of %s: %s", user.first_name, 'user_photo.jpg') update.message.reply_text('Gorgeous! Now, send me your location please, ' @@ -65,7 +65,7 @@ def photo(bot, update): return LOCATION -def skip_photo(bot, update): +def skip_photo(update, context): user = update.message.from_user logger.info("User %s did not send a photo.", user.first_name) update.message.reply_text('I bet you look great! Now, send me your location please, ' @@ -74,7 +74,7 @@ def skip_photo(bot, update): return LOCATION -def location(bot, update): +def location(update, context): user = update.message.from_user user_location = update.message.location logger.info("Location of %s: %f / %f", user.first_name, user_location.latitude, @@ -85,7 +85,7 @@ def location(bot, update): return BIO -def skip_location(bot, update): +def skip_location(update, context): user = update.message.from_user logger.info("User %s did not send a location.", user.first_name) update.message.reply_text('You seem a bit paranoid! ' @@ -94,7 +94,7 @@ def skip_location(bot, update): return BIO -def bio(bot, update): +def bio(update, context): user = update.message.from_user logger.info("Bio of %s: %s", user.first_name, update.message.text) update.message.reply_text('Thank you! I hope we can talk again some day.') @@ -102,7 +102,7 @@ def bio(bot, update): return ConversationHandler.END -def cancel(bot, update): +def cancel(update, context): user = update.message.from_user logger.info("User %s canceled the conversation.", user.first_name) update.message.reply_text('Bye! I hope we can talk again some day.', @@ -111,14 +111,16 @@ def cancel(bot, update): return ConversationHandler.END -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) def main(): - # Create the EventHandler and pass it your bot's token. - updater = Updater("TOKEN") + # Create the Updater and pass it your bot's token. + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/examples/conversationbot2.py b/examples/conversationbot2.py index 34002792a07..59d0d751c9a 100644 --- a/examples/conversationbot2.py +++ b/examples/conversationbot2.py @@ -17,12 +17,12 @@ bot. """ +import logging + from telegram import ReplyKeyboardMarkup from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler, ConversationHandler) -import logging - # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) @@ -46,7 +46,7 @@ def facts_to_str(user_data): return "\n".join(facts).join(['\n', '\n']) -def start(bot, update): +def start(update, context): update.message.reply_text( "Hi! My name is Doctor Botter. I will hold a more complex conversation with you. " "Why don't you tell me something about yourself?", @@ -55,23 +55,24 @@ def start(bot, update): return CHOOSING -def regular_choice(bot, update, user_data): +def regular_choice(update, context): text = update.message.text - user_data['choice'] = text + context.user_data['choice'] = text update.message.reply_text( 'Your {}? Yes, I would love to hear about that!'.format(text.lower())) return TYPING_REPLY -def custom_choice(bot, update): +def custom_choice(update, context): update.message.reply_text('Alright, please send me the category first, ' 'for example "Most impressive skill"') return TYPING_CHOICE -def received_information(bot, update, user_data): +def received_information(update, context): + user_data = context.user_data text = update.message.text category = user_data['choice'] user_data[category] = text @@ -85,7 +86,8 @@ def received_information(bot, update, user_data): return CHOOSING -def done(bot, update, user_data): +def done(update, context): + user_data = context.user_data if 'choice' in user_data: del user_data['choice'] @@ -97,14 +99,16 @@ def done(bot, update, user_data): return ConversationHandler.END -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" logger.warning('Update "%s" caused error "%s"', update, error) def main(): # Create the Updater and pass it your bot's token. - updater = Updater("TOKEN") + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/examples/echobot2.py b/examples/echobot2.py index d6b102bcdfb..868a03f024b 100644 --- a/examples/echobot2.py +++ b/examples/echobot2.py @@ -17,9 +17,10 @@ bot. """ -from telegram.ext import Updater, CommandHandler, MessageHandler, Filters import logging +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters + # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) @@ -29,30 +30,32 @@ # Define a few command handlers. These usually take the two arguments bot and # update. Error handlers also receive the raised TelegramError object in error. -def start(bot, update): +def start(update, context): """Send a message when the command /start is issued.""" update.message.reply_text('Hi!') -def help(bot, update): +def help(update, context): """Send a message when the command /help is issued.""" update.message.reply_text('Help!') -def echo(bot, update): +def echo(update, context): """Echo the user message.""" update.message.reply_text(update.message.text) -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) def main(): """Start the bot.""" - # Create the EventHandler and pass it your bot's token. - updater = Updater("TOKEN") + # Create the Updater and pass it your bot's token. + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/examples/inlinebot.py b/examples/inlinebot.py index 923e6bd7975..4c4c896891b 100644 --- a/examples/inlinebot.py +++ b/examples/inlinebot.py @@ -16,14 +16,13 @@ Press Ctrl-C on the command line or send a signal to the process to stop the bot. """ +import logging from uuid import uuid4 -from telegram.utils.helpers import escape_markdown - from telegram import InlineQueryResultArticle, ParseMode, \ InputTextMessageContent from telegram.ext import Updater, InlineQueryHandler, CommandHandler -import logging +from telegram.utils.helpers import escape_markdown # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', @@ -34,17 +33,17 @@ # Define a few command handlers. These usually take the two arguments bot and # update. Error handlers also receive the raised TelegramError object in error. -def start(bot, update): +def start(update, context): """Send a message when the command /start is issued.""" update.message.reply_text('Hi!') -def help(bot, update): +def help(update, context): """Send a message when the command /help is issued.""" update.message.reply_text('Help!') -def inlinequery(bot, update): +def inlinequery(update, context): """Handle the inline query.""" query = update.inline_query.query results = [ @@ -69,14 +68,16 @@ def inlinequery(bot, update): update.inline_query.answer(results) -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) def main(): # Create the Updater and pass it your bot's token. - updater = Updater("TOKEN") + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/examples/inlinekeyboard.py b/examples/inlinekeyboard.py index 84c0966adc0..8b699f932b3 100644 --- a/examples/inlinekeyboard.py +++ b/examples/inlinekeyboard.py @@ -5,6 +5,7 @@ # This program is dedicated to the public domain under the CC0 license. """ import logging + from telegram import InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import Updater, CommandHandler, CallbackQueryHandler @@ -13,7 +14,7 @@ logger = logging.getLogger(__name__) -def start(bot, update): +def start(update, context): keyboard = [[InlineKeyboardButton("Option 1", callback_data='1'), InlineKeyboardButton("Option 2", callback_data='2')], @@ -24,26 +25,26 @@ def start(bot, update): update.message.reply_text('Please choose:', reply_markup=reply_markup) -def button(bot, update): +def button(update, context): query = update.callback_query - bot.edit_message_text(text="Selected option: {}".format(query.data), - chat_id=query.message.chat_id, - message_id=query.message.message_id) + query.edit_message_text(text="Selected option: {}".format(query.data)) -def help(bot, update): +def help(update, context): update.message.reply_text("Use /start to test this bot.") -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) def main(): # Create the Updater and pass it your bot's token. - updater = Updater("TOKEN") + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) updater.dispatcher.add_handler(CommandHandler('start', start)) updater.dispatcher.add_handler(CallbackQueryHandler(button)) diff --git a/examples/paymentbot.py b/examples/paymentbot.py index a419034de94..9fc7de0d909 100644 --- a/examples/paymentbot.py +++ b/examples/paymentbot.py @@ -6,10 +6,11 @@ This program is dedicated to the public domain under the CC0 license. """ +import logging + from telegram import (LabeledPrice, ShippingOption) from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, PreCheckoutQueryHandler, ShippingQueryHandler) -import logging # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', @@ -18,18 +19,18 @@ logger = logging.getLogger(__name__) -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) -def start_callback(bot, update): +def start_callback(update, context): msg = "Use /shipping to get an invoice for shipping-payment, " msg += "or /noshipping for an invoice without shipping." update.message.reply_text(msg) -def start_with_shipping_callback(bot, update): +def start_with_shipping_callback(update, context): chat_id = update.message.chat_id title = "Payment Example" description = "Payment Example using python-telegram-bot" @@ -47,13 +48,13 @@ def start_with_shipping_callback(bot, update): # optionally pass need_name=True, need_phone_number=True, # need_email=True, need_shipping_address=True, is_flexible=True - bot.sendInvoice(chat_id, title, description, payload, - provider_token, start_parameter, currency, prices, - need_name=True, need_phone_number=True, - need_email=True, need_shipping_address=True, is_flexible=True) + context.bot.send_invoice(chat_id, title, description, payload, + provider_token, start_parameter, currency, prices, + need_name=True, need_phone_number=True, + need_email=True, need_shipping_address=True, is_flexible=True) -def start_without_shipping_callback(bot, update): +def start_without_shipping_callback(update, context): chat_id = update.message.chat_id title = "Payment Example" description = "Payment Example using python-telegram-bot" @@ -70,17 +71,17 @@ def start_without_shipping_callback(bot, update): # optionally pass need_name=True, need_phone_number=True, # need_email=True, need_shipping_address=True, is_flexible=True - bot.sendInvoice(chat_id, title, description, payload, - provider_token, start_parameter, currency, prices) + context.bot.send_invoice(chat_id, title, description, payload, + provider_token, start_parameter, currency, prices) -def shipping_callback(bot, update): +def shipping_callback(update, context): query = update.shipping_query # check the payload, is this from your bot? if query.invoice_payload != 'Custom-Payload': # answer False pre_checkout_query - bot.answer_shipping_query(shipping_query_id=query.id, ok=False, - error_message="Something went wrong...") + query.answer(shipping_query_id=query.id, ok=False, + error_message="Something went wrong...") return else: options = list() @@ -89,31 +90,33 @@ def shipping_callback(bot, update): # an array of LabeledPrice objects price_list = [LabeledPrice('B1', 150), LabeledPrice('B2', 200)] options.append(ShippingOption('2', 'Shipping Option B', price_list)) - bot.answer_shipping_query(shipping_query_id=query.id, ok=True, - shipping_options=options) + query.answer(shipping_query_id=query.id, ok=True, + shipping_options=options) # after (optional) shipping, it's the pre-checkout -def precheckout_callback(bot, update): +def precheckout_callback(update, context): query = update.pre_checkout_query # check the payload, is this from your bot? if query.invoice_payload != 'Custom-Payload': # answer False pre_checkout_query - bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=False, - error_message="Something went wrong...") + query.answer(pre_checkout_query_id=query.id, ok=False, + error_message="Something went wrong...") else: - bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=True) + query.answer(pre_checkout_query_id=query.id, ok=True) # finally, after contacting to the payment provider... -def successful_payment_callback(bot, update): +def successful_payment_callback(update, context): # do something after successful receive of payment? update.message.reply_text("Thank you for your payment!") def main(): - # Create the EventHandler and pass it your bot's token. - updater = Updater(token="BOT_TOKEN") + # Create the Updater and pass it your bot's token. + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/examples/timerbot.py b/examples/timerbot.py index 1a1c7ff9447..c21563a55d7 100644 --- a/examples/timerbot.py +++ b/examples/timerbot.py @@ -19,9 +19,10 @@ bot. """ -from telegram.ext import Updater, CommandHandler import logging +from telegram.ext import Updater, CommandHandler + # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) @@ -31,28 +32,29 @@ # Define a few command handlers. These usually take the two arguments bot and # update. Error handlers also receive the raised TelegramError object in error. -def start(bot, update): +def start(update, context): update.message.reply_text('Hi! Use /set to set a timer') -def alarm(bot, job): +def alarm(context): """Send the alarm message.""" - bot.send_message(job.context, text='Beep!') + job = context.job + context.bot.send_message(job.context, text='Beep!') -def set_timer(bot, update, args, job_queue, chat_data): +def set_timer(update, context): """Add a job to the queue.""" chat_id = update.message.chat_id try: # args[0] should contain the time for the timer in seconds - due = int(args[0]) + due = int(context.args[0]) if due < 0: update.message.reply_text('Sorry we can not go back to future!') return # Add job to queue - job = job_queue.run_once(alarm, due, context=chat_id) - chat_data['job'] = job + job = context.job_queue.run_once(alarm, due, context=chat_id) + context.chat_data['job'] = job update.message.reply_text('Timer successfully set!') @@ -60,27 +62,30 @@ def set_timer(bot, update, args, job_queue, chat_data): update.message.reply_text('Usage: /set ') -def unset(bot, update, chat_data): +def unset(update, context): """Remove the job if the user changed their mind.""" - if 'job' not in chat_data: + if 'job' not in context.chat_data: update.message.reply_text('You have no active timer') return - job = chat_data['job'] + job = context.chat_data['job'] job.schedule_removal() - del chat_data['job'] + del context.chat_data['job'] update.message.reply_text('Timer successfully unset!') -def error(bot, update, error): +def error(update, context): """Log Errors caused by Updates.""" - logger.warning('Update "%s" caused error "%s"', update, error) + logger.warning('Update "%s" caused error "%s"', update, context.error) def main(): """Run bot.""" - updater = Updater("TOKEN") + # Create the Updater and pass it your bot's token. + # Make sure to set use_context=True to use the new context based callbacks + # Post version 12 this will no longer be necessary + updater = Updater("TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher diff --git a/telegram/ext/__init__.py b/telegram/ext/__init__.py index 87dbf6069a7..4538567dcc1 100644 --- a/telegram/ext/__init__.py +++ b/telegram/ext/__init__.py @@ -18,13 +18,14 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """Extensions over the Telegram Bot API to facilitate bot making""" +from .handler import Handler +from .callbackcontext import CallbackContext from .dispatcher import Dispatcher, DispatcherHandlerStop, run_async from .jobqueue import JobQueue, Job from .updater import Updater from .callbackqueryhandler import CallbackQueryHandler from .choseninlineresulthandler import ChosenInlineResultHandler from .commandhandler import CommandHandler -from .handler import Handler, HandlerContext from .inlinequeryhandler import InlineQueryHandler from .messagehandler import MessageHandler from .filters import BaseFilter, Filters @@ -43,4 +44,4 @@ 'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler', 'StringRegexHandler', 'TypeHandler', 'ConversationHandler', 'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue', - 'DispatcherHandlerStop', 'run_async', 'HandlerContext') + 'DispatcherHandlerStop', 'run_async', 'CallbackContext') diff --git a/telegram/ext/callbackcontext.py b/telegram/ext/callbackcontext.py new file mode 100644 index 00000000000..43a52ff9728 --- /dev/null +++ b/telegram/ext/callbackcontext.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# +# A library that provides a Python interface to the Telegram Bot API +# Copyright (C) 2015-2018 +# Leandro Toledo de Souza +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser Public License for more details. +# +# You should have received a copy of the GNU Lesser Public License +# along with this program. If not, see [http://www.gnu.org/licenses/]. +"""This module contains the CallbackContext class.""" + +from telegram import Update + + +class CallbackContext(object): + """ + This is a context object passed to the callback called by :class:`telegram.ext.Handler` + or by the :class:`telegram.ext.Dispatcher` in an error handler added by + :attr:`telegram.ext.Dispatcher.add_error_handler` or to the callback of a + :class:`telegram.ext.Job`. + + Attributes: + chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same chat it will be the same ``dict``. + user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each + update from the same user it will be the same ``dict``. + match (:obj:`re match object`, optional): If the associated update originated from a + regex-supported handler, this will contain the object returned from + ``re.match(pattern, string)``. + args (List[:obj:`str`], optional): Arguments passed to a command if the associated update + is handled by :class:`telegram.ext.CommandHandler` or + :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the text + after the command, using any whitespace string as a delimiter. + error (:class:`telegram.TelegramError`, optional): The Telegram error that was raised. + Only present when passed to a error handler registered with + :attr:`telegram.ext.Dispatcher.add_error_handler`. + job (:class:`telegram.ext.Job`): The job that that originated this callback. + Only present when passed to the callback of :class:`telegram.ext.Job`. + + """ + + def __init__(self, dispatcher): + """ + Args: + dispatcher (:class:`telegram.ext.Dispatcher`): + """ + self._dispatcher = dispatcher + self.chat_data = None + self.user_data = None + self.args = None + self.match = None + self.error = None + self.job = None + + @classmethod + def from_error(cls, update, error, dispatcher): + self = cls.from_update(update, dispatcher) + self.error = error + return self + + @classmethod + def from_update(cls, update, dispatcher): + self = cls(dispatcher) + if update is not None and isinstance(update, Update): + chat = update.effective_chat + user = update.effective_user + + if chat: + self.chat_data = dispatcher.chat_data[chat.id] + if user: + self.user_data = dispatcher.user_data[user.id] + return self + + @classmethod + def from_job(cls, job, dispatcher): + self = cls(dispatcher) + self.job = job + return self + + @property + def bot(self): + """:class:`telegram.Bot`: The bot associated with this context.""" + return self._dispatcher.bot + + @property + def job_queue(self): + """ + :class:`telegram.ext.JobQueue`: The ``JobQueue`` used by the + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegram.ext.Updater` + associated with this context. + + """ + return self._dispatcher.job_queue + + @property + def update_queue(self): + """ + :class:`queue.Queue`: The ``Queue`` instance used by the + :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegram.ext.Updater` + associated with this context. + + """ + return self._dispatcher.update_queue diff --git a/telegram/ext/callbackqueryhandler.py b/telegram/ext/callbackqueryhandler.py index 0d36b7b23ea..03135d8e991 100644 --- a/telegram/ext/callbackqueryhandler.py +++ b/telegram/ext/callbackqueryhandler.py @@ -47,9 +47,6 @@ class CallbackQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -57,15 +54,15 @@ class CallbackQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -73,34 +70,32 @@ class CallbackQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pattern (:obj:`str` | `Pattern`, optional): Regex pattern. If not ``None``, ``re.match`` is used on :attr:`telegram.CallbackQuery.data` to determine if an update should be handled by this handler. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ + def __init__(self, callback, pass_update_queue=False, @@ -109,15 +104,13 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_user_data=False, - pass_chat_data=False, - use_context=False): + pass_chat_data=False): super(CallbackQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) + pass_chat_data=pass_chat_data) if isinstance(pattern, string_types): pattern = re.compile(pattern) diff --git a/telegram/ext/choseninlineresulthandler.py b/telegram/ext/choseninlineresulthandler.py index f5e831dbeae..09e327410a9 100644 --- a/telegram/ext/choseninlineresulthandler.py +++ b/telegram/ext/choseninlineresulthandler.py @@ -35,9 +35,6 @@ class ChosenInlineResultHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -45,15 +42,15 @@ class ChosenInlineResultHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -61,21 +58,18 @@ class ChosenInlineResultHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ diff --git a/telegram/ext/commandhandler.py b/telegram/ext/commandhandler.py index 817a6de59d0..2f58ebf9a58 100644 --- a/telegram/ext/commandhandler.py +++ b/telegram/ext/commandhandler.py @@ -47,9 +47,6 @@ class CommandHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -57,8 +54,8 @@ class CommandHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: command (:obj:`str` | List[:obj:`str`]): The command or list of commands this handler @@ -67,7 +64,7 @@ class CommandHandler(Handler): :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -81,26 +78,23 @@ class CommandHandler(Handler): arguments passed to the command as a keyword argument called ``args``. It will contain a list of strings, which is the text following the command split on single or consecutive whitespace characters. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ @@ -113,15 +107,13 @@ def __init__(self, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False, - use_context=False): + pass_chat_data=False): super(CommandHandler, self).__init__( callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) + pass_chat_data=pass_chat_data) if isinstance(command, string_types): self.command = [command.lower()] diff --git a/telegram/ext/dispatcher.py b/telegram/ext/dispatcher.py index 6e061abeaba..a7e988573f5 100644 --- a/telegram/ext/dispatcher.py +++ b/telegram/ext/dispatcher.py @@ -32,7 +32,8 @@ from future.builtins import range from telegram import TelegramError -from telegram.ext.handler import Handler, HandlerContext +from telegram.ext.handler import Handler +from telegram.ext.callbackcontext import CallbackContext from telegram.utils.deprecate import TelegramDeprecationWarning from telegram.utils.promise import Promise @@ -80,6 +81,9 @@ class Dispatcher(object): instance to pass onto handler callbacks. workers (:obj:`int`, optional): Number of maximum concurrent worker threads for the ``@run_async`` decorator. defaults to 4. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. """ @@ -88,11 +92,22 @@ class Dispatcher(object): __singleton = None logger = logging.getLogger(__name__) - def __init__(self, bot, update_queue, workers=4, exception_event=None, job_queue=None): + def __init__(self, + bot, + update_queue, + workers=4, + exception_event=None, + job_queue=None, + use_context=False): self.bot = bot self.update_queue = update_queue self.job_queue = job_queue self.workers = workers + self.use_context = use_context + + if not use_context: + warnings.warn('Old Handler API is deprecated - see https://git.io/vp113 for details', + TelegramDeprecationWarning, stacklevel=3) self.user_data = defaultdict(dict) """:obj:`dict`: A dictionary handlers can use to store data for the user.""" @@ -355,27 +370,21 @@ def remove_handler(self, handler, group=DEFAULT_GROUP): del self.handlers[group] self.groups.remove(group) - def add_error_handler(self, callback, use_context=False): + def add_error_handler(self, callback): """Registers an error handler in the Dispatcher. Args: callback (:obj:`callable`): The callback function for this error handler. Will be called when an error is raised Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The error that happened will be present in context.error. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback - API. During the deprecation period of the old API the default is ``False``. - **New users**: set this to ``True``. Note: - See https://git.io/vpVe8 for more info about switching to context based API. + See https://git.io/vp113 for more info about switching to context based API. """ - if not use_context: - warnings.warn('Old Handler API is deprecated - see https://git.io/vpVe8 for details', - TelegramDeprecationWarning, stacklevel=2) - self.error_handlers.append((callback, use_context)) + self.error_handlers.append(callback) def remove_error_handler(self, callback): """Removes an error handler. @@ -384,16 +393,8 @@ def remove_error_handler(self, callback): callback (:obj:`callable`): The error handler to remove. """ - try: - self.error_handlers.remove((callback, True)) - return - except ValueError: - pass - try: - self.error_handlers.remove((callback, False)) - return - except ValueError: - pass + if callback in self.error_handlers: + self.error_handlers.remove(callback) def dispatch_error(self, update, error): """Dispatches an error. @@ -404,9 +405,9 @@ def dispatch_error(self, update, error): """ if self.error_handlers: - for callback, use_context in self.error_handlers: - if use_context: - callback(update, HandlerContext.from_error(update, error, self)) + for callback in self.error_handlers: + if self.use_context: + callback(update, CallbackContext.from_error(update, error, self)) else: callback(self.bot, update, error) diff --git a/telegram/ext/handler.py b/telegram/ext/handler.py index 093aad6ed55..3000ba95ff5 100644 --- a/telegram/ext/handler.py +++ b/telegram/ext/handler.py @@ -17,10 +17,7 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the base class for handlers as used by the Dispatcher.""" -import warnings - -from telegram import Update -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext.callbackcontext import CallbackContext class Handler(object): @@ -36,9 +33,6 @@ class Handler(object): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -46,15 +40,15 @@ class Handler(object): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -62,44 +56,32 @@ class Handler(object): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ + def __init__(self, callback, pass_update_queue=False, pass_job_queue=False, pass_user_data=False, - pass_chat_data=False, - use_context=False): + pass_chat_data=False): self.callback = callback self.pass_update_queue = pass_update_queue self.pass_job_queue = pass_job_queue self.pass_user_data = pass_user_data self.pass_chat_data = pass_chat_data - self.use_context = use_context - - if use_context and ( - pass_update_queue or pass_job_queue or pass_user_data or pass_chat_data): - raise ValueError('Mix of Context Based Handler API and old Handler API is not allowed') - - if not use_context: - warnings.warn('Old Handler API is deprecated - see https://git.io/vpVe8 for details', - TelegramDeprecationWarning, stacklevel=3) def check_update(self, update): """ @@ -131,8 +113,8 @@ def handle_update(self, update, dispatcher, check_result): check_result: The result from :attr:`check_update`. """ - if self.use_context: - context = HandlerContext(update, dispatcher) + if dispatcher.use_context: + context = CallbackContext.from_update(update, dispatcher) self.collect_additional_context(context, update, dispatcher, check_result) return self.callback(update, context) else: @@ -143,7 +125,7 @@ def collect_additional_context(self, context, update, dispatcher, check_result): """Prepares additional arguments for the context. Override if needed. Args: - context (:class:`telegram.ext.HandlerContext`): The context object. + context (:class:`telegram.ext.CallbackContext`): The context object. update (:class:`telegram.Update`): The update to gather chat/user id from. dispatcher (:class:`telegram.ext.Dispatcher`): The calling dispatcher. check_result: The result (return value) from :attr:`check_update`. @@ -156,8 +138,8 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): Prepares the optional arguments. If the handler has additional optional args, it should subclass this method, but remember to call this super method. - DEPRECATED: This method is being replaced by new Context Based Handlers. Please see - https://git.io/vpVe8 for more info. + DEPRECATED: This method is being replaced by new context based callbacks. Please see + https://git.io/vp113 for more info. Args: dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher. @@ -182,79 +164,3 @@ def collect_optional_args(self, dispatcher, update=None, check_result=None): optional_args['chat_data'] = dispatcher.chat_data[chat.id if chat else None] return optional_args - - -class HandlerContext(object): - """This is a context object passed to the callback called by :class:`telegram.ext.Handler`. - - Attributes: - chat_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each - update from the same chat it will be the same ``dict``. - user_data (:obj:`dict`, optional): A dict that can be used to keep any data in. For each - update from the same user it will be the same ``dict``. - match (:obj:`re match object`, optional): If the associated update originated from a - regex-supported handler, this will contain the object returned from - ``re.match(pattern, string)``. - args (List[:obj:`str`], optional): Arguments passed to a command if the associated update - is handled by :class:`telegram.ext.CommandHandler` or - :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the text - after the command, using any whitespace string as a delimiter. - error (:class:`telegram.TelegramError`, optional): The Telegram error that was raised. - Only present when passed to a error handler registered with - :attr:`telegram.ext.Dispatcher.add_error_handler`. - - """ - def __init__(self, update, dispatcher): - """ - Args: - update (:class:`telegram.Update`): - dispatcher (:class:`telegram.ext.Dispatcher`): - - """ - self.update = update - self._dispatcher = dispatcher - self.chat_data = None - self.user_data = None - self.args = None - self.match = None - self.error = None - - if update is not None and isinstance(update, Update): - chat = update.effective_chat - user = update.effective_user - - if chat: - self.chat_data = dispatcher.chat_data[chat.id] - if user: - self.user_data = dispatcher.user_data[user.id] - - @classmethod - def from_error(cls, update, error, dispatcher): - context = cls(update, dispatcher) - context.error = error - return context - - @property - def bot(self): - """:class:`telegram.Bot`: The bot associated with this context.""" - return self._dispatcher.bot - - @property - def job_queue(self): - """ - :class:`telegram.ext.JobQueue`: The ``JobQueue`` used by the - :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegrm.ext.Updater` - associated with this context. - - """ - return self._dispatcher.job_queue - - @property - def update_queue(self): - """ - :class:`queue.Queue`: The ``Queue`` instance used by the - :class:`telegram.ext.Dispatcher` and (usually) the :class:`telegram.ext.Updater` - associated with this context. - - """ - return self._dispatcher.update_queue diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 8a24686faea..3cda05998fc 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -46,9 +46,6 @@ class InlineQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -56,15 +53,15 @@ class InlineQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -72,32 +69,29 @@ class InlineQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pattern (:obj:`str` | :obj:`Pattern`, optional): Regex pattern. If not ``None``, ``re.match`` is used on :attr:`telegram.InlineQuery.query` to determine if an update should be handled by this handler. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ @@ -116,8 +110,7 @@ def __init__(self, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) + pass_chat_data=pass_chat_data) if isinstance(pattern, string_types): pattern = re.compile(pattern) diff --git a/telegram/ext/jobqueue.py b/telegram/ext/jobqueue.py index 1aa51b03fdd..7477105d04c 100644 --- a/telegram/ext/jobqueue.py +++ b/telegram/ext/jobqueue.py @@ -26,6 +26,8 @@ from threading import Thread, Lock, Event from queue import PriorityQueue, Empty +from telegram.ext.callbackcontext import CallbackContext + class Days(object): MON, TUE, WED, THU, FRI, SAT, SUN = range(7) @@ -37,16 +39,12 @@ class JobQueue(object): Attributes: _queue (:obj:`PriorityQueue`): The queue that holds the Jobs. - bot (:class:`telegram.Bot`): Bot that's send to the handlers. - - Args: - bot (:class:`telegram.Bot`): The bot instance that should be passed to the jobs. """ - def __init__(self, bot): + def __init__(self): self._queue = PriorityQueue() - self.bot = bot + self._dispatcher = None self.logger = logging.getLogger(self.__class__.__name__) self.__start_lock = Lock() self.__next_peek_lock = Lock() # to protect self._next_peek & self.__tick @@ -55,6 +53,9 @@ def __init__(self, bot): self._next_peek = None self._running = False + def set_dispatcher(self, dispatcher): + self._dispatcher = dispatcher + def _put(self, job, next_t=None, last_t=None): if next_t is None: next_t = job.interval @@ -242,7 +243,7 @@ def tick(self): current_week_day = datetime.datetime.now().weekday() if any(day == current_week_day for day in job.days): self.logger.debug('Running job %s', job.name) - job.run(self.bot) + job.run(self._dispatcher) except Exception: self.logger.exception('An uncaught error was raised while executing job %s', @@ -367,9 +368,12 @@ def __init__(self, self._enabled = Event() self._enabled.set() - def run(self, bot): + def run(self, dispatcher): """Executes the callback function.""" - self.callback(bot, self) + if dispatcher.use_context: + self.callback(CallbackContext.from_job(self, dispatcher)) + else: + self.callback(dispatcher.bot, self) def schedule_removal(self): """ diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index 2b6cbd6dd7e..aab4fed61b4 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -47,9 +47,6 @@ class MessageHandler(Handler): Default is ``False``. allow_edited (:obj:`bool`): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -57,8 +54,8 @@ class MessageHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: filters (:class:`telegram.ext.BaseFilter`, optional): A filter inheriting from @@ -69,7 +66,7 @@ class MessageHandler(Handler): :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -77,18 +74,18 @@ class MessageHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. message_updates (:obj:`bool`, optional): Should "normal" message updates be handled? Default is ``True``. channel_post_updates (:obj:`bool`, optional): Should channel posts updates be handled? @@ -97,9 +94,6 @@ class MessageHandler(Handler): is ``False``. allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. - use_context (:obj:`bool`, optional): If set to ``True``, all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Raises: ValueError @@ -116,8 +110,7 @@ def __init__(self, pass_chat_data=False, message_updates=True, channel_post_updates=True, - edited_updates=False, - use_context=False): + edited_updates=False): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') @@ -130,8 +123,7 @@ def __init__(self, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) + pass_chat_data=pass_chat_data) self.filters = filters self.message_updates = message_updates self.channel_post_updates = channel_post_updates diff --git a/telegram/ext/precheckoutqueryhandler.py b/telegram/ext/precheckoutqueryhandler.py index b20a3100da1..07f6bef302b 100644 --- a/telegram/ext/precheckoutqueryhandler.py +++ b/telegram/ext/precheckoutqueryhandler.py @@ -35,9 +35,6 @@ class PreCheckoutQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -45,37 +42,34 @@ class PreCheckoutQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ diff --git a/telegram/ext/regexhandler.py b/telegram/ext/regexhandler.py index 5924723ebfb..9dbbbac6541 100644 --- a/telegram/ext/regexhandler.py +++ b/telegram/ext/regexhandler.py @@ -50,9 +50,6 @@ class RegexHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -60,8 +57,8 @@ class RegexHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. @@ -69,34 +66,34 @@ class RegexHandler(Handler): :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. message_updates (:obj:`bool`, optional): Should "normal" message updates be handled? Default is ``True``. channel_post_updates (:obj:`bool`, optional): Should channel posts updates be handled? @@ -105,9 +102,6 @@ class RegexHandler(Handler): is ``False``. allow_edited (:obj:`bool`, optional): If the handler should also accept edited messages. Default is ``False`` - Deprecated. use edited_updates instead. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. Raises: ValueError @@ -126,8 +120,7 @@ def __init__(self, allow_edited=False, message_updates=True, channel_post_updates=False, - edited_updates=False, - use_context=False): + edited_updates=False): if not message_updates and not channel_post_updates and not edited_updates: raise ValueError( 'message_updates, channel_post_updates and edited_updates are all False') @@ -140,8 +133,7 @@ def __init__(self, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue, pass_user_data=pass_user_data, - pass_chat_data=pass_chat_data, - use_context=use_context) + pass_chat_data=pass_chat_data) if isinstance(pattern, string_types): pattern = re.compile(pattern) diff --git a/telegram/ext/shippingqueryhandler.py b/telegram/ext/shippingqueryhandler.py index d9ec190c9c4..8e07d4f47be 100644 --- a/telegram/ext/shippingqueryhandler.py +++ b/telegram/ext/shippingqueryhandler.py @@ -35,9 +35,6 @@ class ShippingQueryHandler(Handler): the callback function. pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Note: :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you @@ -45,15 +42,15 @@ class ShippingQueryHandler(Handler): either the user or the chat that the update was sent in. For each update from the same user or in the same chat, it will be the same ``dict``. - Note that this is DEPRECATED, and you should use Context Based Handlers. See - https://git.io/vpVe8 for more info. + Note that this is DEPRECATED, and you should use context based callbacks. See + https://git.io/vp113 for more info. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -61,21 +58,18 @@ class ShippingQueryHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_user_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``user_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``chat_data`` will be passed to the callback function. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ diff --git a/telegram/ext/stringcommandhandler.py b/telegram/ext/stringcommandhandler.py index 80691280d5b..01e4936d592 100644 --- a/telegram/ext/stringcommandhandler.py +++ b/telegram/ext/stringcommandhandler.py @@ -39,16 +39,13 @@ class StringCommandHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Args: callback (:obj:`callable`): The callback function for this handler. Will be called when :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -56,20 +53,17 @@ class StringCommandHandler(Handler): arguments passed to the command as a keyword argument called ``args``. It will contain a list of strings, which is the text following the command split on single or consecutive whitespace characters. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ @@ -78,13 +72,11 @@ def __init__(self, callback, pass_args=False, pass_update_queue=False, - pass_job_queue=False, - use_context=False): + pass_job_queue=False): super(StringCommandHandler, self).__init__( callback, pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - use_context=use_context) + pass_job_queue=pass_job_queue) self.command = command self.pass_args = pass_args diff --git a/telegram/ext/stringregexhandler.py b/telegram/ext/stringregexhandler.py index 0d12837d7f5..ba52cce0a96 100644 --- a/telegram/ext/stringregexhandler.py +++ b/telegram/ext/stringregexhandler.py @@ -46,9 +46,6 @@ class StringRegexHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Args: pattern (:obj:`str` | :obj:`Pattern`): The regex pattern. @@ -56,31 +53,28 @@ class StringRegexHandler(Handler): :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. pass_groups (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groups()`` as a keyword argument called ``groups``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_groupdict (:obj:`bool`, optional): If the callback should be passed the result of ``re.match(pattern, data).groupdict()`` as a keyword argument called ``groupdict``. Default is ``False`` - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_update_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ @@ -90,13 +84,11 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_update_queue=False, - pass_job_queue=False, - use_context=False): + pass_job_queue=False): super(StringRegexHandler, self).__init__( callback, pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - use_context=use_context) + pass_job_queue=pass_job_queue) if isinstance(pattern, string_types): pattern = re.compile(pattern) diff --git a/telegram/ext/typehandler.py b/telegram/ext/typehandler.py index cd2584718c0..6d0e015f412 100644 --- a/telegram/ext/typehandler.py +++ b/telegram/ext/typehandler.py @@ -32,9 +32,6 @@ class TypeHandler(Handler): passed to the callback function. pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to the callback function. - use_context (:obj:`bool`): Determines whether all `pass_` arguments will be - ignored in favor of passing a :class:`telegram.ext.HandlerContext` object to the - callback. Args: type (:obj:`type`): The ``type`` of updates this handler should process, as @@ -43,7 +40,7 @@ class TypeHandler(Handler): :attr:`check_update` has determined that an update should be processed by this handler. Callback signature for context based API: - ``def callback(update: Update, context: HandlerContext)`` + ``def callback(update: Update, context: CallbackContext)`` The return value of the callback is usually ignored except for the special case of :class:`telegram.ext.ConversationHandler`. @@ -53,15 +50,12 @@ class TypeHandler(Handler): ``update_queue`` will be passed to the callback function. It will be the ``Queue`` instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher` that contains new updates which can be used to insert updates. Default is ``False``. - DEPRECATED: Please switch to context based handlers. + DEPRECATED: Please switch to context based callbacks. pass_job_queue (:obj:`bool`, optional): If set to ``True``, a keyword argument called ``job_queue`` will be passed to the callback function. It will be a :class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater` which can be used to schedule new jobs. Default is ``False``. - DEPRECATED: Please switch to context based handlers. - use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. - During the deprecation period of the old API the default is ``False``. **New users**: - set this to ``True``. + DEPRECATED: Please switch to context based callbacks. """ @@ -70,13 +64,11 @@ def __init__(self, callback, strict=False, pass_update_queue=False, - pass_job_queue=False, - use_context=False): + pass_job_queue=False): super(TypeHandler, self).__init__( callback, pass_update_queue=pass_update_queue, - pass_job_queue=pass_job_queue, - use_context=use_context) + pass_job_queue=pass_job_queue) self.type = type self.strict = strict diff --git a/telegram/ext/updater.py b/telegram/ext/updater.py index 77752ba17d0..89f9576d3d9 100644 --- a/telegram/ext/updater.py +++ b/telegram/ext/updater.py @@ -57,6 +57,7 @@ class Updater(object): dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that handles the updates and dispatches them to the handlers. running (:obj:`bool`): Indicates if the updater is running. + use_context (:obj:`bool`, optional): ``True`` if using context based callbacks. Args: token (:obj:`str`, optional): The bot's token given by the @BotFather. @@ -73,6 +74,9 @@ class Updater(object): `telegram.utils.request.Request` object (ignored if `bot` argument is used). The request_kwargs are very useful for the advanced users who would like to control the default timeouts and/or control the proxy used for http communication. + use_context (:obj:`bool`, optional): If set to ``True`` Use the context based callback API. + During the deprecation period of the old API the default is ``False``. **New users**: + set this to ``True``. Note: You must supply either a :attr:`bot` or a :attr:`token` argument. @@ -90,7 +94,8 @@ def __init__(self, workers=4, bot=None, user_sig_handler=None, - request_kwargs=None): + request_kwargs=None, + use_context=False): if (token is None) and (bot is None): raise ValueError('`token` or `bot` must be passed') @@ -122,14 +127,16 @@ def __init__(self, self.bot = Bot(token, base_url, request=self._request) self.user_sig_handler = user_sig_handler self.update_queue = Queue() - self.job_queue = JobQueue(self.bot) + self.job_queue = JobQueue() self.__exception_event = Event() self.dispatcher = Dispatcher( self.bot, self.update_queue, job_queue=self.job_queue, workers=workers, - exception_event=self.__exception_event) + exception_event=self.__exception_event, + use_context=use_context) + self.job_queue.set_dispatcher(self.dispatcher) self.last_update_id = 0 self.running = False self.is_idle = False diff --git a/tests/conftest.py b/tests/conftest.py index cf500995c34..7796f6f6ae3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -68,7 +68,8 @@ def provider_token(bot_info): def create_dp(bot): # Dispatcher is heavy to init (due to many threads and such) so we have a single session # scoped one here, but before each test, reset it (dp fixture below) - dispatcher = Dispatcher(bot, Queue(), job_queue=JobQueue(bot), workers=2) + dispatcher = Dispatcher(bot, Queue(), job_queue=JobQueue(), workers=2, use_context=False) + dispatcher.job_queue.set_dispatcher(dispatcher) thr = Thread(target=dispatcher.start) thr.start() sleep(2) @@ -105,6 +106,13 @@ def dp(_dp): Dispatcher._Dispatcher__singleton_semaphore.release() +@pytest.fixture(scope='function') +def cdp(dp): + dp.use_context = True + yield dp + dp.use_context = False + + def pytest_configure(config): if sys.version_info >= (3,): config.addinivalue_line('filterwarnings', 'ignore::ResourceWarning') diff --git a/tests/test_callbackqueryhandler.py b/tests/test_callbackqueryhandler.py index d61d060e16e..ca6a81a47b4 100644 --- a/tests/test_callbackqueryhandler.py +++ b/tests/test_callbackqueryhandler.py @@ -22,8 +22,7 @@ from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CallbackQueryHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import CallbackQueryHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -84,7 +83,7 @@ def callback_group(self, bot, update, groups=None, groupdict=None): self.test_flag = groupdict == {'begin': 't', 'end': ' data'} def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -100,7 +99,7 @@ def callback_context_pattern(self, update, context): self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' data'} def test_basic(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_basic, use_context=False) + handler = CallbackQueryHandler(self.callback_basic) dp.add_handler(handler) assert handler.check_update(callback_query) @@ -109,7 +108,7 @@ def test_basic(self, dp, callback_query): assert self.test_flag def test_with_pattern(self, callback_query): - handler = CallbackQueryHandler(self.callback_basic, use_context=False, pattern='.*est.*') + handler = CallbackQueryHandler(self.callback_basic, pattern='.*est.*') assert handler.check_update(callback_query) @@ -117,7 +116,7 @@ def test_with_pattern(self, callback_query): assert not handler.check_update(callback_query) def test_with_passing_group_dict(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_group, use_context=False, + handler = CallbackQueryHandler(self.callback_group, pattern='(?P.*)est(?P.*)', pass_groups=True) dp.add_handler(handler) @@ -126,7 +125,7 @@ def test_with_passing_group_dict(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_group, use_context=False, + handler = CallbackQueryHandler(self.callback_group, pattern='(?P.*)est(?P.*)', pass_groupdict=True) dp.add_handler(handler) @@ -136,7 +135,7 @@ def test_with_passing_group_dict(self, dp, callback_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_data_1, use_context=False, + handler = CallbackQueryHandler(self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -144,7 +143,7 @@ def test_pass_user_or_chat_data(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_data_1, use_context=False, + handler = CallbackQueryHandler(self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -153,7 +152,7 @@ def test_pass_user_or_chat_data(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_data_2, use_context=False, + handler = CallbackQueryHandler(self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -163,7 +162,7 @@ def test_pass_user_or_chat_data(self, dp, callback_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_queue_1, use_context=False, + handler = CallbackQueryHandler(self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -171,7 +170,7 @@ def test_pass_job_or_update_queue(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_queue_1, use_context=False, + handler = CallbackQueryHandler(self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -180,7 +179,7 @@ def test_pass_job_or_update_queue(self, dp, callback_query): assert self.test_flag dp.remove_handler(handler) - handler = CallbackQueryHandler(self.callback_queue_2, use_context=False, + handler = CallbackQueryHandler(self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -190,34 +189,28 @@ def test_pass_job_or_update_queue(self, dp, callback_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = CallbackQueryHandler(self.callback_basic, use_context=False) + handler = CallbackQueryHandler(self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp, callback_query): - handler = CallbackQueryHandler(self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, callback_query): + handler = CallbackQueryHandler(self.callback_context) + cdp.add_handler(handler) - dp.process_update(callback_query) + cdp.process_update(callback_query) assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - CallbackQueryHandler(self.callback_context) - - def test_context_pattern(self, dp, callback_query): + def test_context_pattern(self, cdp, callback_query): handler = CallbackQueryHandler(self.callback_context_pattern, - pattern=r'(?P.*)est(?P.*)', - use_context=True) - dp.add_handler(handler) + pattern=r'(?P.*)est(?P.*)') + cdp.add_handler(handler) - dp.process_update(callback_query) + cdp.process_update(callback_query) assert self.test_flag - dp.remove_handler(handler) + cdp.remove_handler(handler) handler = CallbackQueryHandler(self.callback_context_pattern, - pattern=r'(t)est(.*)', - use_context=True) - dp.add_handler(handler) + pattern=r'(t)est(.*)') + cdp.add_handler(handler) - dp.process_update(callback_query) + cdp.process_update(callback_query) assert self.test_flag diff --git a/tests/test_choseninlineresulthandler.py b/tests/test_choseninlineresulthandler.py index 5936ca3e055..06d8dac438b 100644 --- a/tests/test_choseninlineresulthandler.py +++ b/tests/test_choseninlineresulthandler.py @@ -16,15 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -import sys from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import ChosenInlineResultHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import ChosenInlineResultHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -82,7 +80,7 @@ def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -92,7 +90,7 @@ def callback_context(self, update, context): isinstance(update.chosen_inline_result, ChosenInlineResult)) def test_basic(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_basic, use_context=False) + handler = ChosenInlineResultHandler(self.callback_basic) dp.add_handler(handler) assert handler.check_update(chosen_inline_result) @@ -100,7 +98,7 @@ def test_basic(self, dp, chosen_inline_result): assert self.test_flag def test_pass_user_or_chat_data(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_data_1, use_context=False, + handler = ChosenInlineResultHandler(self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -108,7 +106,7 @@ def test_pass_user_or_chat_data(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_data_1, use_context=False, + handler = ChosenInlineResultHandler(self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -117,7 +115,7 @@ def test_pass_user_or_chat_data(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_data_2, use_context=False, + handler = ChosenInlineResultHandler(self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -126,7 +124,7 @@ def test_pass_user_or_chat_data(self, dp, chosen_inline_result): assert self.test_flag def test_pass_job_or_update_queue(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_queue_1, use_context=False, + handler = ChosenInlineResultHandler(self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -134,7 +132,7 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_queue_1, use_context=False, + handler = ChosenInlineResultHandler(self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -143,7 +141,7 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): assert self.test_flag dp.remove_handler(handler) - handler = ChosenInlineResultHandler(self.callback_queue_2, use_context=False, + handler = ChosenInlineResultHandler(self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -152,17 +150,12 @@ def test_pass_job_or_update_queue(self, dp, chosen_inline_result): assert self.test_flag def test_other_update_types(self, false_update): - handler = ChosenInlineResultHandler(self.callback_basic, use_context=False) + handler = ChosenInlineResultHandler(self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp, chosen_inline_result): - handler = ChosenInlineResultHandler(self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, chosen_inline_result): + handler = ChosenInlineResultHandler(self.callback_context) + cdp.add_handler(handler) - dp.process_update(chosen_inline_result) + cdp.process_update(chosen_inline_result) assert self.test_flag - - @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - ChosenInlineResultHandler(self.callback_context) diff --git a/tests/test_commandhandler.py b/tests/test_commandhandler.py index b11a8e868e6..6264f9d77eb 100644 --- a/tests/test_commandhandler.py +++ b/tests/test_commandhandler.py @@ -22,8 +22,7 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import CommandHandler, Filters, BaseFilter, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import CommandHandler, Filters, BaseFilter, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='test') @@ -86,7 +85,7 @@ def ch_callback_args(self, bot, update, args): self.test_flag = args == ['one', 'two'] def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -99,7 +98,7 @@ def callback_context_args(self, update, context): self.test_flag = context.args == ['one', 'two'] def test_basic(self, dp, message): - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) dp.add_handler(handler) message.text = '/test' @@ -119,7 +118,7 @@ def test_basic(self, dp, message): assert check is None or check is False def test_command_list(self, message): - handler = CommandHandler(['test', 'start'], self.callback_basic, use_context=False) + handler = CommandHandler(['test', 'start'], self.callback_basic) message.text = '/test' check = handler.check_update(Update(0, message)) @@ -132,7 +131,7 @@ def test_command_list(self, message): assert check is None or check is False def test_edited(self, message): - handler = CommandHandler('test', self.callback_basic, use_context=False, + handler = CommandHandler('test', self.callback_basic, allow_edited=False) message.text = '/test' @@ -147,7 +146,7 @@ def test_edited(self, message): assert check is not None and check is not False def test_directed_commands(self, message): - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) message.text = '/test@{}'.format(message.bot.username) check = handler.check_update(Update(0, message)) @@ -157,7 +156,7 @@ def test_directed_commands(self, message): assert not handler.check_update(Update(0, message)) def test_with_filter(self, message): - handler = CommandHandler('test', self.callback_basic, Filters.group, use_context=False) + handler = CommandHandler('test', self.callback_basic, Filters.group) message.chat = Chat(-23, 'group') message.text = '/test' @@ -169,7 +168,7 @@ def test_with_filter(self, message): assert check is None or check is False def test_pass_args(self, dp, message): - handler = CommandHandler('test', self.ch_callback_args, use_context=False, pass_args=True) + handler = CommandHandler('test', self.ch_callback_args, pass_args=True) dp.add_handler(handler) message.text = '/test' @@ -192,7 +191,7 @@ def test_pass_args(self, dp, message): assert self.test_flag def test_newline(self, dp, message): - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) dp.add_handler(handler) message.text = '/test\nfoobar' @@ -203,7 +202,7 @@ def test_newline(self, dp, message): def test_single_char(self, dp, message): # Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/871 - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) dp.add_handler(handler) message.text = 'a' @@ -212,7 +211,7 @@ def test_single_char(self, dp, message): def test_single_slash(self, dp, message): # Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/871 - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) dp.add_handler(handler) message.text = '/' @@ -224,7 +223,7 @@ def test_single_slash(self, dp, message): assert check is None or check is False def test_pass_user_or_chat_data(self, dp, message): - handler = CommandHandler('test', self.callback_data_1, use_context=False, + handler = CommandHandler('test', self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -233,7 +232,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_data_1, use_context=False, + handler = CommandHandler('test', self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -242,7 +241,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_data_2, use_context=False, + handler = CommandHandler('test', self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -252,7 +251,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = CommandHandler('test', self.callback_queue_1, use_context=False, + handler = CommandHandler('test', self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -261,7 +260,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_queue_1, use_context=False, + handler = CommandHandler('test', self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -270,7 +269,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = CommandHandler('test', self.callback_queue_2, use_context=False, + handler = CommandHandler('test', self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -280,7 +279,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = CommandHandler('test', self.callback_basic, use_context=False) + handler = CommandHandler('test', self.callback_basic) check = handler.check_update(false_update) assert check is None or check is False @@ -296,7 +295,7 @@ def filter(self, message): test_filter = TestFilter() - handler = CommandHandler('foo', self.callback_basic, use_context=False, + handler = CommandHandler('foo', self.callback_basic, filters=test_filter) message.text = '/bar' @@ -305,26 +304,22 @@ def filter(self, message): assert not test_filter.tested - def test_context(self, dp, message): - handler = CommandHandler('test', self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, message): + handler = CommandHandler('test', self.callback_context) + cdp.add_handler(handler) message.text = '/test' - dp.process_update(Update(0, message)) + cdp.process_update(Update(0, message)) assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - CommandHandler('test', self.callback_context) - - def test_context_args(self, dp, message): - handler = CommandHandler('test', self.callback_context_args, use_context=True) - dp.add_handler(handler) + def test_context_args(self, cdp, message): + handler = CommandHandler('test', self.callback_context_args) + cdp.add_handler(handler) message.text = '/test' - dp.process_update(Update(0, message)) + cdp.process_update(Update(0, message)) assert not self.test_flag message.text = '/test one two' - dp.process_update(Update(0, message)) + cdp.process_update(Update(0, message)) assert self.test_flag diff --git a/tests/test_dispatcher.py b/tests/test_dispatcher.py index 90e5fab963e..bb31e3f5a06 100644 --- a/tests/test_dispatcher.py +++ b/tests/test_dispatcher.py @@ -24,7 +24,7 @@ import pytest from telegram import TelegramError, Message, User, Chat, Update, Bot -from telegram.ext import MessageHandler, Filters, CommandHandler, HandlerContext, JobQueue +from telegram.ext import MessageHandler, Filters, CommandHandler, CallbackContext, JobQueue from telegram.ext.dispatcher import run_async, Dispatcher, DispatcherHandlerStop from telegram.utils.deprecate import TelegramDeprecationWarning from tests.conftest import create_dp @@ -70,7 +70,7 @@ def callback_if_not_update_queue(self, bot, update, update_queue=None): self.received = update.message def callback_context(self, update, context): - if (isinstance(context, HandlerContext) and + if (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and @@ -327,15 +327,16 @@ def error(b, u, e): assert passed == ['start1', 'error', err] assert passed[2] is err - def test_context(self, dp): - dp.add_error_handler(self.callback_context, True) + def test_error_handler_context(self, cdp): + cdp.add_error_handler(self.callback_context) error = TelegramError('Unauthorized.') - dp.update_queue.put(error) + cdp.update_queue.put(error) sleep(.1) assert self.received == 'Unauthorized.' @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') def test_non_context_deprecation(self, dp): with pytest.warns(TelegramDeprecationWarning): - dp.add_error_handler(self.callback_context) + Dispatcher(dp.bot, dp.update_queue, job_queue=dp.job_queue, workers=0, + use_context=False) diff --git a/tests/test_inlinequeryhandler.py b/tests/test_inlinequeryhandler.py index 0bb6eb14fd3..689f1ad10db 100644 --- a/tests/test_inlinequeryhandler.py +++ b/tests/test_inlinequeryhandler.py @@ -22,8 +22,7 @@ from telegram import (Update, CallbackQuery, Bot, Message, User, Chat, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery, Location) -from telegram.ext import InlineQueryHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import InlineQueryHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -88,7 +87,7 @@ def callback_group(self, bot, update, groups=None, groupdict=None): self.test_flag = groupdict == {'begin': 't', 'end': ' query'} def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -104,7 +103,7 @@ def callback_context_pattern(self, update, context): self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' query'} def test_basic(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_basic, use_context=False) + handler = InlineQueryHandler(self.callback_basic) dp.add_handler(handler) assert handler.check_update(inline_query) @@ -113,7 +112,7 @@ def test_basic(self, dp, inline_query): assert self.test_flag def test_with_pattern(self, inline_query): - handler = InlineQueryHandler(self.callback_basic, use_context=False, + handler = InlineQueryHandler(self.callback_basic, pattern='(?P.*)est(?P.*)') assert handler.check_update(inline_query) @@ -122,7 +121,7 @@ def test_with_pattern(self, inline_query): assert not handler.check_update(inline_query) def test_with_passing_group_dict(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_group, use_context=False, + handler = InlineQueryHandler(self.callback_group, pattern='(?P.*)est(?P.*)', pass_groups=True) dp.add_handler(handler) @@ -131,7 +130,7 @@ def test_with_passing_group_dict(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_group, use_context=False, + handler = InlineQueryHandler(self.callback_group, pattern='(?P.*)est(?P.*)', pass_groupdict=True) dp.add_handler(handler) @@ -141,14 +140,14 @@ def test_with_passing_group_dict(self, dp, inline_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_data_1, use_context=False, pass_user_data=True) + handler = InlineQueryHandler(self.callback_data_1, pass_user_data=True) dp.add_handler(handler) dp.process_update(inline_query) assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_data_1, use_context=False, pass_chat_data=True) + handler = InlineQueryHandler(self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -156,7 +155,7 @@ def test_pass_user_or_chat_data(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_data_2, use_context=False, pass_chat_data=True, + handler = InlineQueryHandler(self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -165,14 +164,14 @@ def test_pass_user_or_chat_data(self, dp, inline_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_queue_1, use_context=False, pass_job_queue=True) + handler = InlineQueryHandler(self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) dp.process_update(inline_query) assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_queue_1, use_context=False, + handler = InlineQueryHandler(self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -181,7 +180,7 @@ def test_pass_job_or_update_queue(self, dp, inline_query): assert self.test_flag dp.remove_handler(handler) - handler = InlineQueryHandler(self.callback_queue_2, use_context=False, pass_job_queue=True, + handler = InlineQueryHandler(self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -190,34 +189,28 @@ def test_pass_job_or_update_queue(self, dp, inline_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = InlineQueryHandler(self.callback_basic, use_context=False) + handler = InlineQueryHandler(self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp, inline_query): - handler = InlineQueryHandler(self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, inline_query): + handler = InlineQueryHandler(self.callback_context) + cdp.add_handler(handler) - dp.process_update(inline_query) + cdp.process_update(inline_query) assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - InlineQueryHandler(self.callback_context) - - def test_context_pattern(self, dp, inline_query): + def test_context_pattern(self, cdp, inline_query): handler = InlineQueryHandler(self.callback_context_pattern, - pattern=r'(?P.*)est(?P.*)', - use_context=True) - dp.add_handler(handler) + pattern=r'(?P.*)est(?P.*)') + cdp.add_handler(handler) - dp.process_update(inline_query) + cdp.process_update(inline_query) assert self.test_flag - dp.remove_handler(handler) + cdp.remove_handler(handler) handler = InlineQueryHandler(self.callback_context_pattern, - pattern=r'(t)est(.*)', - use_context=True) - dp.add_handler(handler) + pattern=r'(t)est(.*)') + cdp.add_handler(handler) - dp.process_update(inline_query) + cdp.process_update(inline_query) assert self.test_flag diff --git a/tests/test_messagehandler.py b/tests/test_messagehandler.py index e648631db81..1d1d6c8354f 100644 --- a/tests/test_messagehandler.py +++ b/tests/test_messagehandler.py @@ -22,8 +22,7 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import Filters, MessageHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import Filters, MessageHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -76,7 +75,7 @@ def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): def callback_context(self, update, context): self.test_flag = ( - isinstance(context, HandlerContext) and + isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -94,7 +93,7 @@ def callback_context(self, update, context): ) def test_basic(self, dp, message): - handler = MessageHandler(None, self.callback_basic, use_context=False) + handler = MessageHandler(None, self.callback_basic) dp.add_handler(handler) assert handler.check_update(Update(0, message)) @@ -102,7 +101,7 @@ def test_basic(self, dp, message): assert self.test_flag def test_edited(self, message): - handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True, + handler = MessageHandler(None, self.callback_basic, edited_updates=True, message_updates=False, channel_post_updates=False) assert handler.check_update(Update(0, edited_message=message)) @@ -111,7 +110,7 @@ def test_edited(self, message): assert handler.check_update(Update(0, edited_channel_post=message)) def test_channel_post(self, message): - handler = MessageHandler(None, self.callback_basic, use_context=False, + handler = MessageHandler(None, self.callback_basic, edited_updates=False, message_updates=False, channel_post_updates=True) @@ -121,7 +120,7 @@ def test_channel_post(self, message): assert not handler.check_update(Update(0, edited_channel_post=message)) def test_multiple_flags(self, message): - handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True, + handler = MessageHandler(None, self.callback_basic, edited_updates=True, message_updates=True, channel_post_updates=True) assert handler.check_update(Update(0, edited_message=message)) @@ -131,7 +130,7 @@ def test_multiple_flags(self, message): def test_allow_edited(self, message): with pytest.warns(UserWarning): - handler = MessageHandler(None, self.callback_basic, use_context=False, + handler = MessageHandler(None, self.callback_basic, message_updates=True, allow_edited=True, channel_post_updates=False) @@ -142,11 +141,11 @@ def test_allow_edited(self, message): def test_none_allowed(self): with pytest.raises(ValueError, match='are all False'): - MessageHandler(None, self.callback_basic, use_context=False, message_updates=False, + MessageHandler(None, self.callback_basic, message_updates=False, channel_post_updates=False, edited_updates=False) def test_with_filter(self, message): - handler = MessageHandler(Filters.command, self.callback_basic, use_context=False) + handler = MessageHandler(Filters.command, self.callback_basic) message.text = '/test' assert handler.check_update(Update(0, message)) @@ -155,7 +154,7 @@ def test_with_filter(self, message): assert not handler.check_update(Update(0, message)) def test_pass_user_or_chat_data(self, dp, message): - handler = MessageHandler(None, self.callback_data_1, use_context=False, + handler = MessageHandler(None, self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -163,7 +162,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_data_1, use_context=False, + handler = MessageHandler(None, self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -172,7 +171,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_data_2, use_context=False, + handler = MessageHandler(None, self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -181,7 +180,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = MessageHandler(None, self.callback_queue_1, use_context=False, + handler = MessageHandler(None, self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -189,7 +188,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_queue_1, use_context=False, + handler = MessageHandler(None, self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -198,7 +197,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = MessageHandler(None, self.callback_queue_2, use_context=False, + handler = MessageHandler(None, self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -207,29 +206,25 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = MessageHandler(None, self.callback_basic, use_context=False, edited_updates=True) + handler = MessageHandler(None, self.callback_basic, edited_updates=True) assert not handler.check_update(false_update) - def test_context(self, dp, message): - handler = MessageHandler(None, self.callback_context, use_context=True, + def test_context(self, cdp, message): + handler = MessageHandler(None, self.callback_context, edited_updates=True, channel_post_updates=True) - dp.add_handler(handler) + cdp.add_handler(handler) - dp.process_update(Update(0, message=message)) + cdp.process_update(Update(0, message=message)) assert self.test_flag self.test_flag = False - dp.process_update(Update(0, edited_message=message)) + cdp.process_update(Update(0, edited_message=message)) assert self.test_flag self.test_flag = False - dp.process_update(Update(0, channel_post=message)) + cdp.process_update(Update(0, channel_post=message)) assert self.test_flag self.test_flag = False - dp.process_update(Update(0, edited_channel_post=message)) + cdp.process_update(Update(0, edited_channel_post=message)) assert self.test_flag - - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - MessageHandler(None, self.callback_context) diff --git a/tests/test_precheckoutqueryhandler.py b/tests/test_precheckoutqueryhandler.py index cedc307e399..a5cfba99d9f 100644 --- a/tests/test_precheckoutqueryhandler.py +++ b/tests/test_precheckoutqueryhandler.py @@ -16,15 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -import sys from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery) -from telegram.ext import PreCheckoutQueryHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import PreCheckoutQueryHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -82,7 +80,7 @@ def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -92,7 +90,7 @@ def callback_context(self, update, context): isinstance(update.pre_checkout_query, PreCheckoutQuery)) def test_basic(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_basic, use_context=False) + handler = PreCheckoutQueryHandler(self.callback_basic) dp.add_handler(handler) assert handler.check_update(pre_checkout_query) @@ -100,7 +98,7 @@ def test_basic(self, dp, pre_checkout_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_data_1, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -108,7 +106,7 @@ def test_pass_user_or_chat_data(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_data_1, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -117,7 +115,7 @@ def test_pass_user_or_chat_data(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_data_2, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -127,7 +125,7 @@ def test_pass_user_or_chat_data(self, dp, pre_checkout_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_queue_1, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -135,7 +133,7 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_queue_1, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -144,7 +142,7 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): assert self.test_flag dp.remove_handler(handler) - handler = PreCheckoutQueryHandler(self.callback_queue_2, use_context=False, + handler = PreCheckoutQueryHandler(self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -154,17 +152,12 @@ def test_pass_job_or_update_queue(self, dp, pre_checkout_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = PreCheckoutQueryHandler(self.callback_basic, use_context=False) + handler = PreCheckoutQueryHandler(self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp, pre_checkout_query): - handler = PreCheckoutQueryHandler(self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, pre_checkout_query): + handler = PreCheckoutQueryHandler(self.callback_context) + cdp.add_handler(handler) - dp.process_update(pre_checkout_query) + cdp.process_update(pre_checkout_query) assert self.test_flag - - @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - PreCheckoutQueryHandler(self.callback_context) diff --git a/tests/test_regexhandler.py b/tests/test_regexhandler.py index 508ef82bae8..6e3af9766b0 100644 --- a/tests/test_regexhandler.py +++ b/tests/test_regexhandler.py @@ -22,8 +22,7 @@ from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import RegexHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import RegexHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -81,7 +80,7 @@ def callback_group(self, bot, update, groups=None, groupdict=None): self.test_flag = groupdict == {'begin': 't', 'end': ' message'} def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -97,7 +96,7 @@ def callback_context_pattern(self, update, context): self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' message'} def test_basic(self, dp, message): - handler = RegexHandler('.*', self.callback_basic, use_context=False) + handler = RegexHandler('.*', self.callback_basic) dp.add_handler(handler) assert handler.check_update(Update(0, message)) @@ -105,16 +104,15 @@ def test_basic(self, dp, message): assert self.test_flag def test_pattern(self, message): - handler = RegexHandler('.*est.*', self.callback_basic, use_context=False) + handler = RegexHandler('.*est.*', self.callback_basic) assert handler.check_update(Update(0, message)) - handler = RegexHandler('.*not in here.*', self.callback_basic, use_context=False) + handler = RegexHandler('.*not in here.*', self.callback_basic) assert not handler.check_update(Update(0, message)) def test_with_passing_group_dict(self, dp, message): handler = RegexHandler('(?P.*)est(?P.*)', self.callback_group, - use_context=False, pass_groups=True) dp.add_handler(handler) @@ -123,7 +121,6 @@ def test_with_passing_group_dict(self, dp, message): dp.remove_handler(handler) handler = RegexHandler('(?P.*)est(?P.*)', self.callback_group, - use_context=False, pass_groupdict=True) dp.add_handler(handler) @@ -132,7 +129,7 @@ def test_with_passing_group_dict(self, dp, message): assert self.test_flag def test_edited(self, message): - handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True, + handler = RegexHandler('.*', self.callback_basic, edited_updates=True, message_updates=False, channel_post_updates=False) assert handler.check_update(Update(0, edited_message=message)) @@ -141,7 +138,7 @@ def test_edited(self, message): assert handler.check_update(Update(0, edited_channel_post=message)) def test_channel_post(self, message): - handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=False, + handler = RegexHandler('.*', self.callback_basic, edited_updates=False, message_updates=False, channel_post_updates=True) assert not handler.check_update(Update(0, edited_message=message)) @@ -150,7 +147,7 @@ def test_channel_post(self, message): assert not handler.check_update(Update(0, edited_channel_post=message)) def test_multiple_flags(self, message): - handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True, + handler = RegexHandler('.*', self.callback_basic, edited_updates=True, message_updates=True, channel_post_updates=True) assert handler.check_update(Update(0, edited_message=message)) @@ -160,7 +157,7 @@ def test_multiple_flags(self, message): def test_allow_edited(self, message): with pytest.warns(UserWarning): - handler = RegexHandler('.*', self.callback_basic, use_context=False, + handler = RegexHandler('.*', self.callback_basic, message_updates=True, allow_edited=True) @@ -171,18 +168,18 @@ def test_allow_edited(self, message): def test_none_allowed(self): with pytest.raises(ValueError, match='are all False'): - RegexHandler('.*', self.callback_basic, use_context=False, message_updates=False, + RegexHandler('.*', self.callback_basic, message_updates=False, channel_post_updates=False, edited_updates=False) def test_pass_user_or_chat_data(self, dp, message): - handler = RegexHandler('.*', self.callback_data_1, use_context=False, pass_user_data=True) + handler = RegexHandler('.*', self.callback_data_1, pass_user_data=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_data_1, use_context=False, pass_chat_data=True) + handler = RegexHandler('.*', self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) self.test_flag = False @@ -190,7 +187,7 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_data_2, use_context=False, pass_chat_data=True, + handler = RegexHandler('.*', self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -199,14 +196,14 @@ def test_pass_user_or_chat_data(self, dp, message): assert self.test_flag def test_pass_job_or_update_queue(self, dp, message): - handler = RegexHandler('.*', self.callback_queue_1, use_context=False, pass_job_queue=True) + handler = RegexHandler('.*', self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) dp.process_update(Update(0, message=message)) assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_queue_1, use_context=False, + handler = RegexHandler('.*', self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -215,7 +212,7 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag dp.remove_handler(handler) - handler = RegexHandler('.*', self.callback_queue_2, use_context=False, pass_job_queue=True, + handler = RegexHandler('.*', self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -224,30 +221,26 @@ def test_pass_job_or_update_queue(self, dp, message): assert self.test_flag def test_other_update_types(self, false_update): - handler = RegexHandler('.*', self.callback_basic, use_context=False, edited_updates=True) + handler = RegexHandler('.*', self.callback_basic, edited_updates=True) assert not handler.check_update(false_update) - def test_context(self, dp, message): - handler = RegexHandler(r'(t)est(.*)', self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, message): + handler = RegexHandler(r'(t)est(.*)', self.callback_context) + cdp.add_handler(handler) - dp.process_update(Update(0, message=message)) + cdp.process_update(Update(0, message=message)) assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - RegexHandler('test', self.callback_context) - - def test_context_pattern(self, dp, message): - handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern, use_context=True) - dp.add_handler(handler) + def test_context_pattern(self, cdp, message): + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + cdp.add_handler(handler) - dp.process_update(Update(0, message=message)) + cdp.process_update(Update(0, message=message)) assert self.test_flag - dp.remove_handler(handler) - handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern, use_context=True) - dp.add_handler(handler) + cdp.remove_handler(handler) + handler = RegexHandler(r'(t)est(.*)', self.callback_context_pattern) + cdp.add_handler(handler) - dp.process_update(Update(0, message=message)) + cdp.process_update(Update(0, message=message)) assert self.test_flag diff --git a/tests/test_shippingqueryhandler.py b/tests/test_shippingqueryhandler.py index 82d39db049a..64e70b69697 100644 --- a/tests/test_shippingqueryhandler.py +++ b/tests/test_shippingqueryhandler.py @@ -16,15 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -import sys from queue import Queue import pytest from telegram import (Update, Chat, Bot, ChosenInlineResult, User, Message, CallbackQuery, InlineQuery, ShippingQuery, PreCheckoutQuery, ShippingAddress) -from telegram.ext import ShippingQueryHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import ShippingQueryHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -83,7 +81,7 @@ def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, Update) and isinstance(context.update_queue, Queue) and @@ -93,7 +91,7 @@ def callback_context(self, update, context): isinstance(update.shipping_query, ShippingQuery)) def test_basic(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_basic, use_context=False) + handler = ShippingQueryHandler(self.callback_basic) dp.add_handler(handler) assert handler.check_update(shiping_query) @@ -101,7 +99,7 @@ def test_basic(self, dp, shiping_query): assert self.test_flag def test_pass_user_or_chat_data(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_data_1, use_context=False, + handler = ShippingQueryHandler(self.callback_data_1, pass_user_data=True) dp.add_handler(handler) @@ -109,7 +107,7 @@ def test_pass_user_or_chat_data(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_data_1, use_context=False, + handler = ShippingQueryHandler(self.callback_data_1, pass_chat_data=True) dp.add_handler(handler) @@ -118,7 +116,7 @@ def test_pass_user_or_chat_data(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_data_2, use_context=False, + handler = ShippingQueryHandler(self.callback_data_2, pass_chat_data=True, pass_user_data=True) dp.add_handler(handler) @@ -128,7 +126,7 @@ def test_pass_user_or_chat_data(self, dp, shiping_query): assert self.test_flag def test_pass_job_or_update_queue(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_queue_1, use_context=False, + handler = ShippingQueryHandler(self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -136,7 +134,7 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_queue_1, use_context=False, + handler = ShippingQueryHandler(self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -145,7 +143,7 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): assert self.test_flag dp.remove_handler(handler) - handler = ShippingQueryHandler(self.callback_queue_2, use_context=False, + handler = ShippingQueryHandler(self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -155,17 +153,12 @@ def test_pass_job_or_update_queue(self, dp, shiping_query): assert self.test_flag def test_other_update_types(self, false_update): - handler = ShippingQueryHandler(self.callback_basic, use_context=False) + handler = ShippingQueryHandler(self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp, shiping_query): - handler = ShippingQueryHandler(self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp, shiping_query): + handler = ShippingQueryHandler(self.callback_context) + cdp.add_handler(handler) - dp.process_update(shiping_query) + cdp.process_update(shiping_query) assert self.test_flag - - @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - ShippingQueryHandler(self.callback_context) diff --git a/tests/test_stringcommandhandler.py b/tests/test_stringcommandhandler.py index 20f66e59dc0..52aa1ae23d4 100644 --- a/tests/test_stringcommandhandler.py +++ b/tests/test_stringcommandhandler.py @@ -22,8 +22,7 @@ from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringCommandHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import StringCommandHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -75,7 +74,7 @@ def sch_callback_args(self, bot, update, args): self.test_flag = args == ['one', 'two'] def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, str) and isinstance(context.update_queue, Queue) and @@ -87,7 +86,7 @@ def callback_context_args(self, update, context): self.test_flag = context.args == ['one', 'two'] def test_basic(self, dp): - handler = StringCommandHandler('test', self.callback_basic, use_context=False) + handler = StringCommandHandler('test', self.callback_basic) dp.add_handler(handler) check = handler.check_update('/test') @@ -103,7 +102,7 @@ def test_basic(self, dp): assert check is not None and check is not False def test_pass_args(self, dp): - handler = StringCommandHandler('test', self.sch_callback_args, use_context=False, + handler = StringCommandHandler('test', self.sch_callback_args, pass_args=True) dp.add_handler(handler) @@ -115,7 +114,7 @@ def test_pass_args(self, dp): assert self.test_flag def test_pass_job_or_update_queue(self, dp): - handler = StringCommandHandler('test', self.callback_queue_1, use_context=False, + handler = StringCommandHandler('test', self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -123,7 +122,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringCommandHandler('test', self.callback_queue_1, use_context=False, + handler = StringCommandHandler('test', self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -132,7 +131,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringCommandHandler('test', self.callback_queue_2, use_context=False, + handler = StringCommandHandler('test', self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -142,26 +141,22 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag def test_other_update_types(self, false_update): - handler = StringCommandHandler('test', self.callback_basic, use_context=False) + handler = StringCommandHandler('test', self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp): - handler = StringCommandHandler('test', self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp): + handler = StringCommandHandler('test', self.callback_context) + cdp.add_handler(handler) - dp.process_update('/test') + cdp.process_update('/test') assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - StringCommandHandler('test', self.callback_context) - - def test_context_args(self, dp): - handler = StringCommandHandler('test', self.callback_context_args, use_context=True) - dp.add_handler(handler) + def test_context_args(self, cdp): + handler = StringCommandHandler('test', self.callback_context_args) + cdp.add_handler(handler) - dp.process_update('/test') + cdp.process_update('/test') assert not self.test_flag - dp.process_update('/test one two') + cdp.process_update('/test one two') assert self.test_flag diff --git a/tests/test_stringregexhandler.py b/tests/test_stringregexhandler.py index bfb4156b962..cc09350e37c 100644 --- a/tests/test_stringregexhandler.py +++ b/tests/test_stringregexhandler.py @@ -22,8 +22,7 @@ from telegram import (Bot, Update, Message, User, Chat, CallbackQuery, InlineQuery, ChosenInlineResult, ShippingQuery, PreCheckoutQuery) -from telegram.ext import StringRegexHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import StringRegexHandler, CallbackContext, JobQueue message = Message(1, User(1, '', False), None, Chat(1, ''), text='Text') @@ -75,7 +74,7 @@ def callback_group(self, bot, update, groups=None, groupdict=None): self.test_flag = groupdict == {'begin': 't', 'end': ' message'} def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, str) and isinstance(context.update_queue, Queue) and @@ -88,8 +87,7 @@ def callback_context_pattern(self, update, context): self.test_flag = context.match.groupdict() == {'begin': 't', 'end': ' message'} def test_basic(self, dp): - handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic, - use_context=False) + handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_basic) dp.add_handler(handler) assert handler.check_update('test message') @@ -100,7 +98,7 @@ def test_basic(self, dp): def test_with_passing_group_dict(self, dp): handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_group, - use_context=False, pass_groups=True) + pass_groups=True) dp.add_handler(handler) dp.process_update('test message') @@ -108,7 +106,7 @@ def test_with_passing_group_dict(self, dp): dp.remove_handler(handler) handler = StringRegexHandler('(?P.*)est(?P.*)', self.callback_group, - use_context=False, pass_groupdict=True) + pass_groupdict=True) dp.add_handler(handler) self.test_flag = False @@ -116,7 +114,7 @@ def test_with_passing_group_dict(self, dp): assert self.test_flag def test_pass_job_or_update_queue(self, dp): - handler = StringRegexHandler('test', self.callback_queue_1, use_context=False, + handler = StringRegexHandler('test', self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) @@ -124,7 +122,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringRegexHandler('test', self.callback_queue_1, use_context=False, + handler = StringRegexHandler('test', self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -133,7 +131,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = StringRegexHandler('test', self.callback_queue_2, use_context=False, + handler = StringRegexHandler('test', self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -142,32 +140,26 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag def test_other_update_types(self, false_update): - handler = StringRegexHandler('test', self.callback_basic, use_context=False) + handler = StringRegexHandler('test', self.callback_basic) assert not handler.check_update(false_update) - def test_context(self, dp): - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp): + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context) + cdp.add_handler(handler) - dp.process_update('test message') + cdp.process_update('test message') assert self.test_flag - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - StringRegexHandler('test', self.callback_context) - - def test_context_pattern(self, dp): - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern, - use_context=True) - dp.add_handler(handler) + def test_context_pattern(self, cdp): + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + cdp.add_handler(handler) - dp.process_update('test message') + cdp.process_update('test message') assert self.test_flag - dp.remove_handler(handler) - handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern, - use_context=True) - dp.add_handler(handler) + cdp.remove_handler(handler) + handler = StringRegexHandler(r'(t)est(.*)', self.callback_context_pattern) + cdp.add_handler(handler) - dp.process_update('test message') + cdp.process_update('test message') assert self.test_flag diff --git a/tests/test_typehandler.py b/tests/test_typehandler.py index e389ed339f2..f0fc362a06b 100644 --- a/tests/test_typehandler.py +++ b/tests/test_typehandler.py @@ -22,8 +22,7 @@ import pytest from telegram import Bot -from telegram.ext import TypeHandler, HandlerContext, JobQueue -from telegram.utils.deprecate import TelegramDeprecationWarning +from telegram.ext import TypeHandler, CallbackContext, JobQueue class TestTypeHandler(object): @@ -45,7 +44,7 @@ def callback_queue_2(self, bot, update, job_queue=None, update_queue=None): self.test_flag = (job_queue is not None) and (update_queue is not None) def callback_context(self, update, context): - self.test_flag = (isinstance(context, HandlerContext) and + self.test_flag = (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(update, dict) and isinstance(context.update_queue, Queue) and @@ -54,7 +53,7 @@ def callback_context(self, update, context): context.chat_data is None) def test_basic(self, dp): - handler = TypeHandler(dict, self.callback_basic, use_context=False) + handler = TypeHandler(dict, self.callback_basic) dp.add_handler(handler) assert handler.check_update({'a': 1, 'b': 2}) @@ -63,20 +62,20 @@ def test_basic(self, dp): assert self.test_flag def test_strict(self): - handler = TypeHandler(dict, self.callback_basic, use_context=False, strict=True) + handler = TypeHandler(dict, self.callback_basic, strict=True) o = OrderedDict({'a': 1, 'b': 2}) assert handler.check_update({'a': 1, 'b': 2}) assert not handler.check_update(o) def test_pass_job_or_update_queue(self, dp): - handler = TypeHandler(dict, self.callback_queue_1, use_context=False, pass_job_queue=True) + handler = TypeHandler(dict, self.callback_queue_1, pass_job_queue=True) dp.add_handler(handler) dp.process_update({'a': 1, 'b': 2}) assert self.test_flag dp.remove_handler(handler) - handler = TypeHandler(dict, self.callback_queue_1, use_context=False, + handler = TypeHandler(dict, self.callback_queue_1, pass_update_queue=True) dp.add_handler(handler) @@ -85,7 +84,7 @@ def test_pass_job_or_update_queue(self, dp): assert self.test_flag dp.remove_handler(handler) - handler = TypeHandler(dict, self.callback_queue_2, use_context=False, pass_job_queue=True, + handler = TypeHandler(dict, self.callback_queue_2, pass_job_queue=True, pass_update_queue=True) dp.add_handler(handler) @@ -93,13 +92,9 @@ def test_pass_job_or_update_queue(self, dp): dp.process_update({'a': 1, 'b': 2}) assert self.test_flag - def test_context(self, dp): - handler = TypeHandler(dict, self.callback_context, use_context=True) - dp.add_handler(handler) + def test_context(self, cdp): + handler = TypeHandler(dict, self.callback_context) + cdp.add_handler(handler) - dp.process_update({'a': 1, 'b': 2}) + cdp.process_update({'a': 1, 'b': 2}) assert self.test_flag - - def test_non_context_deprecation(self): - with pytest.warns(TelegramDeprecationWarning): - TypeHandler(dict, self.callback_context) From 256a9d149e51c6bd040533c888222f8f9e767916 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 10 May 2018 17:54:39 +0200 Subject: [PATCH 29/32] Forgot about conversationhandler --- tests/test_conversationhandler.py | 40 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/tests/test_conversationhandler.py b/tests/test_conversationhandler.py index 51967db9d38..2cb2c22c6bc 100644 --- a/tests/test_conversationhandler.py +++ b/tests/test_conversationhandler.py @@ -50,22 +50,22 @@ class TestConversationHandler(object): @pytest.fixture(autouse=True) def reset(self): self.current_state = dict() - self.entry_points = [CommandHandler('start', self.start, use_context=False)] + self.entry_points = [CommandHandler('start', self.start)] self.states = { - self.THIRSTY: [CommandHandler('brew', self.brew, use_context=False), - CommandHandler('wait', self.start, use_context=False)], - self.BREWING: [CommandHandler('pourCoffee', self.drink, use_context=False)], + self.THIRSTY: [CommandHandler('brew', self.brew), + CommandHandler('wait', self.start)], + self.BREWING: [CommandHandler('pourCoffee', self.drink)], self.DRINKING: - [CommandHandler('startCoding', self.code, use_context=False), - CommandHandler('drinkMore', self.drink, use_context=False), - CommandHandler('end', self.end, use_context=False)], + [CommandHandler('startCoding', self.code), + CommandHandler('drinkMore', self.drink), + CommandHandler('end', self.end)], self.CODING: [ - CommandHandler('keepCoding', self.code, use_context=False), - CommandHandler('gettingThirsty', self.start, use_context=False), - CommandHandler('drinkMore', self.drink, use_context=False) + CommandHandler('keepCoding', self.code), + CommandHandler('gettingThirsty', self.start), + CommandHandler('drinkMore', self.drink) ], } - self.fallbacks = [CommandHandler('eat', self.start, use_context=False)] + self.fallbacks = [CommandHandler('eat', self.start)] # State handlers def _set_state(self, update, state): @@ -233,9 +233,9 @@ def two(bot, update): return ConversationHandler.END handler = ConversationHandler( - entry_points=[CallbackQueryHandler(entry, use_context=False)], - states={1: [CallbackQueryHandler(one, use_context=False)], - 2: [CallbackQueryHandler(two, use_context=False)]}, + entry_points=[CallbackQueryHandler(entry)], + states={1: [CallbackQueryHandler(one)], + 2: [CallbackQueryHandler(two)]}, fallbacks=[], per_message=True) dp.add_handler(handler) @@ -261,7 +261,7 @@ def two(bot, update): def test_end_on_first_message(self, dp, bot, user1): handler = ConversationHandler( - entry_points=[CommandHandler('start', self.start_end, use_context=False)], states={}, + entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) dp.add_handler(handler) @@ -274,7 +274,7 @@ def test_end_on_first_message_async(self, dp, bot, user1): start_end_async = (lambda bot, update: dp.run_async(self.start_end, bot, update)) handler = ConversationHandler( - entry_points=[CommandHandler('start', start_end_async, use_context=False)], states={}, + entry_points=[CommandHandler('start', start_end_async)], states={}, fallbacks=[]) dp.add_handler(handler) @@ -294,23 +294,21 @@ def test_end_on_first_message_async(self, dp, bot, user1): def test_per_chat_message_without_chat(self, bot, user1): handler = ConversationHandler( - entry_points=[CommandHandler('start', self.start_end, use_context=False)], states={}, + entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) cbq = CallbackQuery(0, user1, None, None, bot=bot) update = Update(0, callback_query=cbq) assert not handler.check_update(update) def test_channel_message_without_chat(self, bot): - handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end, - use_context=False)], + handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) message = Message(0, None, None, Chat(0, Chat.CHANNEL, 'Misses Test'), bot=bot) update = Update(0, message=message) assert not handler.check_update(update) def test_all_update_types(self, dp, bot, user1): - handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end, - use_context=False)], + handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) message = Message(0, user1, None, self.group, text='ignore', bot=bot) callback_query = CallbackQuery(0, user1, None, message=message, data='data', bot=bot) From 63f8a0712e1801bd55350a596c1be4f57700c00e Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Thu, 10 May 2018 18:16:17 +0200 Subject: [PATCH 30/32] Forgot jobqueue --- CHANGES.rst | 1 + telegram/ext/jobqueue.py | 21 +++++++++++++++++---- tests/test_jobqueue.py | 12 ++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2536849f5e3..ccd939f1d6a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ See https://git.io/vp113 for help. - Instead use `use_context=True` on `Updater` or `Dispatcher` and change callback from (bot, update, others...) to (update, context). - This also applies to error handlers `Dispatcher.add_error_handler` and JobQueue jobs (change (bot, job) to (context) here). - For users with custom handlers subclassing Handler, this is mostly backwards compatible, but to use the new context based callbacks you need to implement the new collect_additional_context method. +- Passing bot to JobQueue.__init__ is deprecated. Use JobQueue.set_dispatcher with a dispatcher instead. Other: - Handlers should be faster due to deduped logic. diff --git a/telegram/ext/jobqueue.py b/telegram/ext/jobqueue.py index 7477105d04c..c0a908070fa 100644 --- a/telegram/ext/jobqueue.py +++ b/telegram/ext/jobqueue.py @@ -18,15 +18,17 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains the classes JobQueue and Job.""" +import datetime import logging import time -import datetime +import warnings import weakref from numbers import Number -from threading import Thread, Lock, Event from queue import PriorityQueue, Empty +from threading import Thread, Lock, Event from telegram.ext.callbackcontext import CallbackContext +from telegram.utils.deprecate import TelegramDeprecationWarning class Days(object): @@ -39,11 +41,22 @@ class JobQueue(object): Attributes: _queue (:obj:`PriorityQueue`): The queue that holds the Jobs. - + bot (:class:`telegram.Bot`): The bot instance that should be passed to the jobs. + DEPRECATED: Use set_dispatcher instead. """ - def __init__(self): + def __init__(self, bot=None): self._queue = PriorityQueue() + if bot: + warnings.warn("Passing bot to jobqueue is deprecated. Please use set_dispatcher " + "instead!", TelegramDeprecationWarning, stacklevel=2) + + class MockDispatcher(object): + def __init__(self): + self.bot = bot + self.use_context = False + + self._dispatcher = MockDispatcher() self._dispatcher = None self.logger = logging.getLogger(self.__class__.__name__) self.__start_lock = Lock() diff --git a/tests/test_jobqueue.py b/tests/test_jobqueue.py index 083a3d1941a..5061d9c0b5c 100644 --- a/tests/test_jobqueue.py +++ b/tests/test_jobqueue.py @@ -22,14 +22,17 @@ from time import sleep import pytest +import sys from flaky import flaky from telegram.ext import JobQueue, Updater, Job +from telegram.utils.deprecate import TelegramDeprecationWarning @pytest.fixture(scope='function') -def job_queue(bot): - jq = JobQueue(bot) +def job_queue(bot, _dp): + jq = JobQueue() + jq.set_dispatcher(_dp) jq.start() yield jq jq.stop() @@ -244,3 +247,8 @@ def test_get_jobs(self, job_queue): assert job_queue.jobs() == (job1, job2, job3) assert job_queue.get_jobs_by_name('name1') == (job1, job2) assert job_queue.get_jobs_by_name('name2') == (job3,) + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') + def test_bot_in_init_deprecation(self, bot): + with pytest.warns(TelegramDeprecationWarning): + JobQueue(bot) From 1fb2e6e724f8d8826d70703e37523b5bf6868eab Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Fri, 11 May 2018 11:22:05 +0200 Subject: [PATCH 31/32] Add tests for callbackcontext & for context based callback job --- telegram/ext/callbackcontext.py | 3 + tests/test_callbackcontext.py | 98 +++++++++++++++++++++++++++++++++ tests/test_jobqueue.py | 26 +++++++-- 3 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 tests/test_callbackcontext.py diff --git a/telegram/ext/callbackcontext.py b/telegram/ext/callbackcontext.py index 43a52ff9728..e36f877c4d1 100644 --- a/telegram/ext/callbackcontext.py +++ b/telegram/ext/callbackcontext.py @@ -53,6 +53,9 @@ def __init__(self, dispatcher): Args: dispatcher (:class:`telegram.ext.Dispatcher`): """ + if not dispatcher.use_context: + raise ValueError('CallbackContext should not be used with a non context aware ' + 'dispatcher!') self._dispatcher = dispatcher self.chat_data = None self.user_data = None diff --git a/tests/test_callbackcontext.py b/tests/test_callbackcontext.py new file mode 100644 index 00000000000..70eb9bcbcf3 --- /dev/null +++ b/tests/test_callbackcontext.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# A library that provides a Python interface to the Telegram Bot API +# Copyright (C) 2015-2018 +# Leandro Toledo de Souza +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser Public License for more details. +# +# You should have received a copy of the GNU Lesser Public License +# along with this program. If not, see [http://www.gnu.org/licenses/]. +import pytest + +from telegram import Update, Message, Chat, User, TelegramError +from telegram.ext import CallbackContext + + +class TestCallbackContext(object): + def test_non_context_dp(self, dp): + with pytest.raises(ValueError): + CallbackContext(dp) + + def test_from_job(self, cdp): + job = cdp.job_queue.run_once(lambda x: x, 10) + + callback_context = CallbackContext.from_job(job, cdp) + + assert callback_context.job is job + assert callback_context.chat_data is None + assert callback_context.user_data is None + assert callback_context.bot is cdp.bot + assert callback_context.job_queue is cdp.job_queue + assert callback_context.update_queue is cdp.update_queue + + def test_from_update(self, cdp): + update = Update(0, message=Message(0, User(1, 'user', False), None, Chat(1, 'chat'))) + + callback_context = CallbackContext.from_update(update, cdp) + + assert callback_context.chat_data == {} + assert callback_context.user_data == {} + assert callback_context.bot is cdp.bot + assert callback_context.job_queue is cdp.job_queue + assert callback_context.update_queue is cdp.update_queue + + callback_context_same_user_chat = CallbackContext.from_update(update, cdp) + + callback_context.chat_data['test'] = 'chat' + callback_context.user_data['test'] = 'user' + + assert callback_context_same_user_chat.chat_data is callback_context.chat_data + assert callback_context_same_user_chat.user_data is callback_context.user_data + + update_other_user_chat = Update(0, message=Message(0, User(2, 'user', False), + None, Chat(2, 'chat'))) + + callback_context_other_user_chat = CallbackContext.from_update(update_other_user_chat, cdp) + + assert callback_context_other_user_chat.chat_data is not callback_context.chat_data + assert callback_context_other_user_chat.user_data is not callback_context.user_data + + def test_from_update_not_update(self, cdp): + callback_context = CallbackContext.from_update(None, cdp) + + assert callback_context.chat_data is None + assert callback_context.user_data is None + assert callback_context.bot is cdp.bot + assert callback_context.job_queue is cdp.job_queue + assert callback_context.update_queue is cdp.update_queue + + callback_context = CallbackContext.from_update('', cdp) + + assert callback_context.chat_data is None + assert callback_context.user_data is None + assert callback_context.bot is cdp.bot + assert callback_context.job_queue is cdp.job_queue + assert callback_context.update_queue is cdp.update_queue + + def test_from_error(self, cdp): + error = TelegramError('test') + + update = Update(0, message=Message(0, User(1, 'user', False), None, Chat(1, 'chat'))) + + callback_context = CallbackContext.from_error(update, error, cdp) + + assert callback_context.error is error + assert callback_context.chat_data == {} + assert callback_context.user_data == {} + assert callback_context.bot is cdp.bot + assert callback_context.job_queue is cdp.job_queue + assert callback_context.update_queue is cdp.update_queue diff --git a/tests/test_jobqueue.py b/tests/test_jobqueue.py index 5061d9c0b5c..e3ed8e6995d 100644 --- a/tests/test_jobqueue.py +++ b/tests/test_jobqueue.py @@ -18,14 +18,15 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. import datetime import os +import sys import time +from queue import Queue from time import sleep import pytest -import sys from flaky import flaky -from telegram.ext import JobQueue, Updater, Job +from telegram.ext import JobQueue, Updater, Job, CallbackContext from telegram.utils.deprecate import TelegramDeprecationWarning @@ -65,6 +66,16 @@ def job_run_once_with_context(self, bot, job): def job_datetime_tests(self, bot, job): self.job_time = time.time() + def job_context_based_callback(self, context): + if (isinstance(context, CallbackContext) and + isinstance(context.job, Job) and + isinstance(context.update_queue, Queue) and + context.job.context == 2 and + context.chat_data is None and + context.user_data is None and + context.job_queue is context.job.job_queue): + self.result += 1 + def test_run_once(self, job_queue): job_queue.run_once(self.job_run_once, 0.01) sleep(0.02) @@ -250,5 +261,12 @@ def test_get_jobs(self, job_queue): @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') def test_bot_in_init_deprecation(self, bot): - with pytest.warns(TelegramDeprecationWarning): - JobQueue(bot) + with pytest.warns(TelegramDeprecationWarning): + JobQueue(bot) + + def test_context_based_callback(self, job_queue): + job_queue.run_once(self.job_context_based_callback, 0.01, context=2) + + sleep(0.03) + + assert self.result == 0 From 9c4dc3cc48e94e03ff0181677e33f963b3c915c1 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Tue, 15 May 2018 11:59:08 +0200 Subject: [PATCH 32/32] Fix as per review :) --- examples/paymentbot.py | 11 ++++------- telegram/ext/inlinequeryhandler.py | 3 +-- telegram/ext/jobqueue.py | 3 ++- telegram/ext/messagehandler.py | 7 +------ 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/examples/paymentbot.py b/examples/paymentbot.py index 9fc7de0d909..f512bb344e7 100644 --- a/examples/paymentbot.py +++ b/examples/paymentbot.py @@ -80,8 +80,7 @@ def shipping_callback(update, context): # check the payload, is this from your bot? if query.invoice_payload != 'Custom-Payload': # answer False pre_checkout_query - query.answer(shipping_query_id=query.id, ok=False, - error_message="Something went wrong...") + query.answer(ok=False, error_message="Something went wrong...") return else: options = list() @@ -90,8 +89,7 @@ def shipping_callback(update, context): # an array of LabeledPrice objects price_list = [LabeledPrice('B1', 150), LabeledPrice('B2', 200)] options.append(ShippingOption('2', 'Shipping Option B', price_list)) - query.answer(shipping_query_id=query.id, ok=True, - shipping_options=options) + query.answer(ok=True, shipping_options=options) # after (optional) shipping, it's the pre-checkout @@ -100,10 +98,9 @@ def precheckout_callback(update, context): # check the payload, is this from your bot? if query.invoice_payload != 'Custom-Payload': # answer False pre_checkout_query - query.answer(pre_checkout_query_id=query.id, ok=False, - error_message="Something went wrong...") + query.answer(ok=False, error_message="Something went wrong...") else: - query.answer(pre_checkout_query_id=query.id, ok=True) + query.answer(ok=True) # finally, after contacting to the payment provider... diff --git a/telegram/ext/inlinequeryhandler.py b/telegram/ext/inlinequeryhandler.py index 3cda05998fc..19a90a10c36 100644 --- a/telegram/ext/inlinequeryhandler.py +++ b/telegram/ext/inlinequeryhandler.py @@ -103,8 +103,7 @@ def __init__(self, pass_groups=False, pass_groupdict=False, pass_user_data=False, - pass_chat_data=False, - use_context=False): + pass_chat_data=False): super(InlineQueryHandler, self).__init__( callback, pass_update_queue=pass_update_queue, diff --git a/telegram/ext/jobqueue.py b/telegram/ext/jobqueue.py index c0a908070fa..2249b1ae708 100644 --- a/telegram/ext/jobqueue.py +++ b/telegram/ext/jobqueue.py @@ -57,7 +57,8 @@ def __init__(self): self.use_context = False self._dispatcher = MockDispatcher() - self._dispatcher = None + else: + self._dispatcher = None self.logger = logging.getLogger(self.__class__.__name__) self.__start_lock = Lock() self.__next_peek_lock = Lock() # to protect self._next_peek & self.__tick diff --git a/telegram/ext/messagehandler.py b/telegram/ext/messagehandler.py index aab4fed61b4..8cd33d82ef5 100644 --- a/telegram/ext/messagehandler.py +++ b/telegram/ext/messagehandler.py @@ -145,12 +145,7 @@ def check_update(self, update): """ if isinstance(update, Update) and self._is_allowed_update(update): - if not self.filters: return True - else: - message = update.effective_message - if self.filters is None: - return True - return self.filters(message) + return self.filters(update.effective_message) 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