Refactor handling of default_quote ()

* 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 ()

* 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 ()

* 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 ()

* 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
This commit is contained in:
Bibo-Joshi 2020-07-19 17:47:26 +02:00
parent 2d4d48b89d
commit 7daddfb54d
14 changed files with 42 additions and 161 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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):

View file

@ -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)

View file

@ -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)

View file

@ -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):

View file

@ -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

View file

@ -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()

View file

@ -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):

View file

@ -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

View file

@ -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()

View file

@ -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())