From 7daddfb54d999836eaa25766660c46aa59cb58e3 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi Date: Sun, 19 Jul 2020 17:47:26 +0200 Subject: [PATCH] Refactor handling of default_quote (#1965) * Refactor handling of `default_quote` * Make it a breaking change * Pickle a bots defaults * Temporarily enable tests for the v13 branch * Temporarily enable tests for the v13 branch * Refactor handling of kwargs in Bot methods (#1924) * Unify kwargs handling in Bot methods * Remove Request.get, make api_kwargs an explicit argument, move note to head of Bot class * Fix test_official * Update get_file methods * Refactor JobQueue (#1981) * First go on refactoring JobQueue * Temporarily enable tests for the v13 branch * Work on tests * Temporarily enable tests for the v13 branch * Increase coverage * Remove JobQueue.tick() * Address review * Temporarily enable tests for the v13 branch * Address review * Dispatch errors * Fix handling of job_kwargs * Remove possibility to pass a Bot to JobQueue * Refactor persistence of Bot instances (#1994) * Refactor persistence of bots * User BP.set_bot in Dispatcher * Temporarily enable tests for the v13 branch * Add documentation * Add warning to Updater for passing both defaults and bot * Address review * Fix test --- telegram/bot.py | 14 ------------- telegram/callbackquery.py | 5 +---- telegram/chat.py | 5 +---- telegram/ext/updater.py | 14 ++++++++----- telegram/message.py | 34 ++++++++++---------------------- telegram/update.py | 25 +++++------------------ telegram/utils/webhookhandler.py | 9 +++------ tests/test_bot.py | 21 -------------------- tests/test_callbackquery.py | 4 +--- tests/test_chat.py | 18 +---------------- tests/test_inputmedia.py | 7 ------- tests/test_message.py | 8 +++++--- tests/test_update.py | 8 -------- tests/test_updater.py | 31 ++++++----------------------- 14 files changed, 42 insertions(+), 161 deletions(-) diff --git a/telegram/bot.py b/telegram/bot.py index 54ed2d52d..c9069716c 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -193,9 +193,6 @@ class Bot(TelegramObject): if result is True: return result - if self.defaults: - result['default_quote'] = self.defaults.quote - return Message.de_json(result, self) @property @@ -1126,10 +1123,6 @@ class Bot(TelegramObject): result = self._post('sendMediaGroup', data, timeout=timeout, api_kwargs=api_kwargs) - if self.defaults: - for res in result: - res['default_quote'] = self.defaults.quote - return [Message.de_json(res, self) for res in result] @log @@ -2190,10 +2183,6 @@ class Bot(TelegramObject): else: self.logger.debug('No new updates found.') - if self.defaults: - for u in result: - u['default_quote'] = self.defaults.quote - return [Update.de_json(u, self) for u in result] @log @@ -2354,9 +2343,6 @@ class Bot(TelegramObject): result = self._post('getChat', data, timeout=timeout, api_kwargs=api_kwargs) - if self.defaults: - result['default_quote'] = self.defaults.quote - return Chat.de_json(result, self) @log diff --git a/telegram/callbackquery.py b/telegram/callbackquery.py index 002481edb..7e8e6b28f 100644 --- a/telegram/callbackquery.py +++ b/telegram/callbackquery.py @@ -105,10 +105,7 @@ class CallbackQuery(TelegramObject): data = super().de_json(data, bot) data['from_user'] = User.de_json(data.get('from'), bot) - message = data.get('message') - if message: - message['default_quote'] = data.get('default_quote') - data['message'] = Message.de_json(message, bot) + data['message'] = Message.de_json(data.get('message'), bot) return cls(bot=bot, **data) diff --git a/telegram/chat.py b/telegram/chat.py index 0cfc81844..a7e781f74 100644 --- a/telegram/chat.py +++ b/telegram/chat.py @@ -149,10 +149,7 @@ class Chat(TelegramObject): data['photo'] = ChatPhoto.de_json(data.get('photo'), bot) from telegram import Message - pinned_message = data.get('pinned_message') - if pinned_message: - pinned_message['default_quote'] = data.get('default_quote') - data['pinned_message'] = Message.de_json(pinned_message, bot) + data['pinned_message'] = Message.de_json(data.get('pinned_message'), bot) data['permissions'] = ChatPermissions.de_json(data.get('permissions'), bot) return cls(bot=bot, **data) diff --git a/telegram/ext/updater.py b/telegram/ext/updater.py index 93b3efb15..cd11ecd27 100644 --- a/telegram/ext/updater.py +++ b/telegram/ext/updater.py @@ -20,6 +20,7 @@ import logging import ssl +import warnings from threading import Thread, Lock, current_thread, Event from time import sleep from signal import signal, SIGINT, SIGTERM, SIGABRT @@ -28,6 +29,7 @@ from queue import Queue from telegram import Bot, TelegramError from telegram.ext import Dispatcher, JobQueue from telegram.error import Unauthorized, InvalidToken, RetryAfter, TimedOut +from telegram.utils.deprecate import TelegramDeprecationWarning from telegram.utils.helpers import get_signal_name from telegram.utils.request import Request from telegram.utils.webhookhandler import (WebhookServer, WebhookAppClass) @@ -116,6 +118,12 @@ class Updater: dispatcher=None, base_file_url=None): + if defaults and bot: + warnings.warn('Passing defaults to an Updater has no effect when a Bot is passed ' + 'as well. Pass them to the Bot instead.', + TelegramDeprecationWarning, + stacklevel=2) + if dispatcher is None: if (token is None) and (bot is None): raise ValueError('`token` or `bot` must be passed') @@ -197,9 +205,6 @@ class Updater: self.__lock = Lock() self.__threads = [] - # Just for passing to WebhookAppClass - self._default_quote = defaults.quote if defaults else None - def _init_thread(self, target, name, *args, **kwargs): thr = Thread(target=self._thread_wrapper, name="Bot:{}:{}".format(self.bot.id, name), @@ -443,8 +448,7 @@ class Updater: url_path = '/{}'.format(url_path) # Create Tornado app instance - app = WebhookAppClass(url_path, self.bot, self.update_queue, - default_quote=self._default_quote) + app = WebhookAppClass(url_path, self.bot, self.update_queue) # Form SSL Context # An SSLError is raised if the private key does not match with the certificate diff --git a/telegram/message.py b/telegram/message.py index 297b5548d..e48f07923 100644 --- a/telegram/message.py +++ b/telegram/message.py @@ -116,8 +116,6 @@ class Message(TelegramObject): reply_markup (:class:`telegram.InlineKeyboardMarkup`): Optional. Inline keyboard attached to the message. bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods. - default_quote (:obj:`bool`): Optional. Default setting for the `quote` parameter of the - :attr:`reply_text` and friends. Args: message_id (:obj:`int`): Unique message identifier inside this chat. @@ -225,8 +223,7 @@ class Message(TelegramObject): via_bot (:class:`telegram.User`, optional): Message was sent through an inline bot. reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): Inline keyboard attached to the message. ``login_url`` buttons are represented as ordinary url buttons. - default_quote (:obj:`bool`, optional): Default setting for the `quote` parameter of the - :attr:`reply_text` and friends. + bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods. """ @@ -290,7 +287,6 @@ class Message(TelegramObject): forward_sender_name=None, reply_markup=None, bot=None, - default_quote=None, dice=None, via_bot=None, **kwargs): @@ -346,7 +342,6 @@ class Message(TelegramObject): self.via_bot = via_bot self.reply_markup = reply_markup self.bot = bot - self.default_quote = default_quote self._id_attrs = (self.message_id, self.chat) @@ -377,22 +372,13 @@ class Message(TelegramObject): data['from_user'] = User.de_json(data.get('from'), bot) data['date'] = from_timestamp(data['date']) - chat = data.get('chat') - if chat: - chat['default_quote'] = data.get('default_quote') - data['chat'] = Chat.de_json(chat, bot) + data['chat'] = Chat.de_json(data.get('chat'), bot) data['entities'] = MessageEntity.de_list(data.get('entities'), bot) data['caption_entities'] = MessageEntity.de_list(data.get('caption_entities'), bot) data['forward_from'] = User.de_json(data.get('forward_from'), bot) - forward_from_chat = data.get('forward_from_chat') - if forward_from_chat: - forward_from_chat['default_quote'] = data.get('default_quote') - data['forward_from_chat'] = Chat.de_json(forward_from_chat, bot) + data['forward_from_chat'] = Chat.de_json(data.get('forward_from_chat'), bot) data['forward_date'] = from_timestamp(data.get('forward_date')) - reply_to_message = data.get('reply_to_message') - if reply_to_message: - reply_to_message['default_quote'] = data.get('default_quote') - data['reply_to_message'] = Message.de_json(reply_to_message, bot) + data['reply_to_message'] = Message.de_json(data.get('reply_to_message'), bot) data['edit_date'] = from_timestamp(data.get('edit_date')) data['audio'] = Audio.de_json(data.get('audio'), bot) data['document'] = Document.de_json(data.get('document'), bot) @@ -409,10 +395,7 @@ class Message(TelegramObject): data['new_chat_members'] = User.de_list(data.get('new_chat_members'), bot) data['left_chat_member'] = User.de_json(data.get('left_chat_member'), bot) data['new_chat_photo'] = PhotoSize.de_list(data.get('new_chat_photo'), bot) - pinned_message = data.get('pinned_message') - if pinned_message: - pinned_message['default_quote'] = data.get('default_quote') - data['pinned_message'] = Message.de_json(pinned_message, bot) + data['pinned_message'] = Message.de_json(data.get('pinned_message'), bot) data['invoice'] = Invoice.de_json(data.get('invoice'), bot) data['successful_payment'] = SuccessfulPayment.de_json(data.get('successful_payment'), bot) data['passport_data'] = PassportData.de_json(data.get('passport_data'), bot) @@ -497,8 +480,11 @@ class Message(TelegramObject): del kwargs['quote'] else: - if ((self.default_quote is None and self.chat.type != Chat.PRIVATE) - or self.default_quote): + if self.bot.defaults: + default_quote = self.bot.defaults.quote + else: + default_quote = None + if (default_quote is None and self.chat.type != Chat.PRIVATE) or default_quote: kwargs['reply_to_message_id'] = self.message_id def reply_text(self, *args, **kwargs): diff --git a/telegram/update.py b/telegram/update.py index 5c2199a43..5e1fa10bd 100644 --- a/telegram/update.py +++ b/telegram/update.py @@ -230,31 +230,16 @@ class Update(TelegramObject): data = super().de_json(data, bot) - message = data.get('message') - if message: - message['default_quote'] = data.get('default_quote') - data['message'] = Message.de_json(message, bot) - edited_message = data.get('edited_message') - if edited_message: - edited_message['default_quote'] = data.get('default_quote') - data['edited_message'] = Message.de_json(edited_message, bot) + data['message'] = Message.de_json(data.get('message'), bot) + data['edited_message'] = Message.de_json(data.get('edited_message'), bot) data['inline_query'] = InlineQuery.de_json(data.get('inline_query'), bot) data['chosen_inline_result'] = ChosenInlineResult.de_json( data.get('chosen_inline_result'), bot) - callback_query = data.get('callback_query') - if callback_query: - callback_query['default_quote'] = data.get('default_quote') - data['callback_query'] = CallbackQuery.de_json(callback_query, bot) + data['callback_query'] = CallbackQuery.de_json(data.get('callback_query'), bot) data['shipping_query'] = ShippingQuery.de_json(data.get('shipping_query'), bot) data['pre_checkout_query'] = PreCheckoutQuery.de_json(data.get('pre_checkout_query'), bot) - channel_post = data.get('channel_post') - if channel_post: - channel_post['default_quote'] = data.get('default_quote') - data['channel_post'] = Message.de_json(channel_post, bot) - edited_channel_post = data.get('edited_channel_post') - if edited_channel_post: - edited_channel_post['default_quote'] = data.get('default_quote') - data['edited_channel_post'] = Message.de_json(edited_channel_post, bot) + data['channel_post'] = Message.de_json(data.get('channel_post'), bot) + data['edited_channel_post'] = Message.de_json(data.get('edited_channel_post'), bot) data['poll'] = Poll.de_json(data.get('poll'), bot) data['poll_answer'] = PollAnswer.de_json(data.get('poll_answer'), bot) diff --git a/telegram/utils/webhookhandler.py b/telegram/utils/webhookhandler.py index 644133774..d5afccf01 100644 --- a/telegram/utils/webhookhandler.py +++ b/telegram/utils/webhookhandler.py @@ -111,9 +111,8 @@ class WebhookServer: class WebhookAppClass(tornado.web.Application): - def __init__(self, webhook_path, bot, update_queue, default_quote=None): - self.shared_objects = {"bot": bot, "update_queue": update_queue, - "default_quote": default_quote} + def __init__(self, webhook_path, bot, update_queue): + self.shared_objects = {"bot": bot, "update_queue": update_queue} handlers = [ (r"{}/?".format(webhook_path), WebhookHandler, self.shared_objects) @@ -132,10 +131,9 @@ class WebhookHandler(tornado.web.RequestHandler): super().__init__(application, request, **kwargs) self.logger = logging.getLogger(__name__) - def initialize(self, bot, update_queue, default_quote=None): + def initialize(self, bot, update_queue): self.bot = bot self.update_queue = update_queue - self._default_quote = default_quote def set_default_headers(self): self.set_header("Content-Type", 'application/json; charset="utf-8"') @@ -147,7 +145,6 @@ class WebhookHandler(tornado.web.RequestHandler): data = json.loads(json_string) self.set_status(200) self.logger.debug('Webhook received data: ' + json_string) - data['default_quote'] = self._default_quote update = Update.de_json(data, self.bot) self.logger.debug('Received Update with ID %d on Webhook' % update.update_id) self.update_queue.put(update) diff --git a/tests/test_bot.py b/tests/test_bot.py index 16c90877c..1beeb79d3 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -726,20 +726,6 @@ class TestBot: assert chat.title == '>>> telegram.Bot(test) @{}'.format(bot.username) assert chat.id == int(super_group_id) - # TODO: Add bot to group to test there too - @flaky(3, 1) - @pytest.mark.timeout(10) - @pytest.mark.parametrize('default_bot', [{'quote': True}], indirect=True) - def test_get_chat_default_quote(self, default_bot, super_group_id): - message = default_bot.send_message(super_group_id, text="test_get_chat_default_quote") - assert default_bot.pin_chat_message(chat_id=super_group_id, message_id=message.message_id, - disable_notification=True) - - chat = default_bot.get_chat(super_group_id) - assert chat.pinned_message.default_quote is True - - assert default_bot.unpinChatMessage(super_group_id) - @flaky(3, 1) @pytest.mark.timeout(10) def test_get_chat_administrators(self, bot, channel_id): @@ -1098,13 +1084,6 @@ class TestBot: assert message.text == test_markdown_string assert message.text_markdown == escape_markdown(test_markdown_string) - @flaky(3, 1) - @pytest.mark.timeout(10) - @pytest.mark.parametrize('default_bot', [{'quote': True}], indirect=True) - def test_send_message_default_quote(self, default_bot, chat_id): - message = default_bot.send_message(chat_id, 'test') - assert message.default_quote is True - @flaky(3, 1) @pytest.mark.timeout(10) def test_set_and_get_my_commands(self, bot): diff --git a/tests/test_callbackquery.py b/tests/test_callbackquery.py index f2648f1ee..183269e59 100644 --- a/tests/test_callbackquery.py +++ b/tests/test_callbackquery.py @@ -53,15 +53,13 @@ class TestCallbackQuery: 'message': self.message.to_dict(), 'data': self.data, 'inline_message_id': self.inline_message_id, - 'game_short_name': self.game_short_name, - 'default_quote': True} + 'game_short_name': self.game_short_name} callback_query = CallbackQuery.de_json(json_dict, bot) assert callback_query.id == self.id_ assert callback_query.from_user == self.from_user assert callback_query.chat_instance == self.chat_instance assert callback_query.message == self.message - assert callback_query.message.default_quote is True assert callback_query.data == self.data assert callback_query.inline_message_id == self.inline_message_id assert callback_query.game_short_name == self.game_short_name diff --git a/tests/test_chat.py b/tests/test_chat.py index bbf203d7f..5ee5b9a2a 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -20,7 +20,7 @@ import pytest from telegram import Chat, ChatAction, ChatPermissions -from telegram import User, Message +from telegram import User @pytest.fixture(scope='class') @@ -72,22 +72,6 @@ class TestChat: assert chat.permissions == self.permissions assert chat.slow_mode_delay == self.slow_mode_delay - def test_de_json_default_quote(self, bot): - json_dict = { - 'id': self.id_, - 'type': self.type_, - 'pinned_message': Message( - message_id=123, - from_user=None, - date=None, - chat=None - ).to_dict(), - 'default_quote': True - } - chat = Chat.de_json(json_dict, bot) - - assert chat.pinned_message.default_quote is True - def test_to_dict(self, chat): chat_dict = chat.to_dict() diff --git a/tests/test_inputmedia.py b/tests/test_inputmedia.py index de76e45af..2f360287e 100644 --- a/tests/test_inputmedia.py +++ b/tests/test_inputmedia.py @@ -348,13 +348,6 @@ class TestSendMediaGroup: assert all([isinstance(mes, Message) for mes in messages]) assert all([mes.media_group_id == messages[0].media_group_id for mes in messages]) - @flaky(3, 1) - @pytest.mark.timeout(10) - @pytest.mark.parametrize('default_bot', [{'quote': True}], indirect=True) - def test_send_media_group_default_quote(self, default_bot, chat_id, media_group): - messages = default_bot.send_media_group(chat_id, media_group) - assert all([mes.default_quote is True for mes in messages]) - @flaky(3, 1) @pytest.mark.timeout(10) def test_edit_message_media(self, bot, chat_id, media_group): diff --git a/tests/test_message.py b/tests/test_message.py index dd74ef54b..46563a517 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -23,6 +23,7 @@ import pytest from telegram import (Update, Message, User, MessageEntity, Chat, Audio, Document, Animation, Game, PhotoSize, Sticker, Video, Voice, VideoNote, Contact, Location, Venue, Invoice, SuccessfulPayment, PassportData, ParseMode, Poll, PollOption, Dice) +from telegram.ext import Defaults from tests.test_passport import RAW_PASSPORT_DATA @@ -864,18 +865,19 @@ class TestMessage: assert message.pin() def test_default_quote(self, message): + message.bot.defaults = Defaults() kwargs = {} - message.default_quote = False + message.bot.defaults._quote = False message._quote(kwargs) assert 'reply_to_message_id' not in kwargs - message.default_quote = True + message.bot.defaults._quote = True message._quote(kwargs) assert 'reply_to_message_id' in kwargs kwargs = {} - message.default_quote = None + message.bot.defaults._quote = None message.chat.type = Chat.PRIVATE message._quote(kwargs) assert 'reply_to_message_id' not in kwargs diff --git a/tests/test_update.py b/tests/test_update.py index 88c221824..196f355e6 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -77,14 +77,6 @@ class TestUpdate: assert update is None - def test_de_json_default_quote(self, bot): - json_dict = {'update_id': TestUpdate.update_id} - json_dict['message'] = message.to_dict() - json_dict['default_quote'] = True - update = Update.de_json(json_dict, bot) - - assert update.message.default_quote is True - def test_to_dict(self, update): update_dict = update.to_dict() diff --git a/tests/test_updater.py b/tests/test_updater.py index 81f2a5498..939ea4da3 100644 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -38,7 +38,8 @@ import pytest from telegram import TelegramError, Message, User, Chat, Update, Bot from telegram.error import Unauthorized, InvalidToken, TimedOut, RetryAfter -from telegram.ext import Updater, Dispatcher, DictPersistence +from telegram.ext import Updater, Dispatcher, DictPersistence, Defaults +from telegram.utils.deprecate import TelegramDeprecationWarning from telegram.utils.webhookhandler import WebhookServer signalskip = pytest.mark.skipif(sys.platform == 'win32', @@ -337,30 +338,6 @@ class TestUpdater: assert q.get(False) == update updater.stop() - def test_webhook_default_quote(self, monkeypatch, updater): - updater._default_quote = True - q = Queue() - monkeypatch.setattr(updater.bot, 'set_webhook', lambda *args, **kwargs: True) - monkeypatch.setattr(updater.bot, 'delete_webhook', lambda *args, **kwargs: True) - monkeypatch.setattr('telegram.ext.Dispatcher.process_update', lambda _, u: q.put(u)) - - ip = '127.0.0.1' - port = randrange(1024, 49152) # Select random port - updater.start_webhook( - ip, - port, - url_path='TOKEN') - sleep(.2) - - # Now, we send an update to the server via urlopen - update = Update(1, message=Message(1, User(1, '', False), None, Chat(1, ''), - text='Webhook')) - self._send_webhook_msg(ip, port, update.to_json(), 'TOKEN') - sleep(.2) - # assert q.get(False) == update - assert q.get(False).message.default_quote is True - updater.stop() - @pytest.mark.parametrize(('error',), argvalues=[(TelegramError(''),)], ids=('TelegramError',)) @@ -581,3 +558,7 @@ class TestUpdater: use_context = not dispatcher.use_context with pytest.raises(ValueError): Updater(dispatcher=dispatcher, use_context=use_context) + + def test_defaults_warning(self, bot): + with pytest.warns(TelegramDeprecationWarning, match='no effect when a Bot is passed'): + Updater(bot=bot, defaults=Defaults())