Skip to content

Commit 810bc30

Browse files
committed
Get started on tests
1 parent c17a8be commit 810bc30

File tree

8 files changed

+112
-129
lines changed

8 files changed

+112
-129
lines changed

telegram/ext/callbackqueryhandler.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,19 @@ class CallbackQueryHandler(Handler[Update]):
4949
Read the documentation of the ``re`` module for more information.
5050
5151
Note:
52-
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
53-
can use to keep any data in will be sent to the :attr:`callback` function. Related to
54-
either the user or the chat that the update was sent in. For each update from the same user
55-
or in the same chat, it will be the same ``dict``.
56-
57-
Note that this is DEPRECATED, and you should use context based callbacks. See
58-
https://git.io/fxJuV for more info.
52+
* :attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
53+
can use to keep any data in will be sent to the :attr:`callback` function. Related to
54+
either the user or the chat that the update was sent in. For each update from the same
55+
user or in the same chat, it will be the same ``dict``.
56+
57+
Note that this is DEPRECATED, and you should use context based callbacks. See
58+
https://git.io/fxJuV for more info.
59+
* If your bot allows arbitrary objects as ``callback_data``, it may happen that the
60+
original ``callback_data`` for the incoming :class:`telegram.CallbackQuery`` can not be
61+
found. This is the case when either a malicious client tempered with the
62+
``callback_data`` or the data was simply dropped from cache or not persisted. In these
63+
cases, an instance of :class:`telegram.ext.utils.callbackdatacache.InvalidCallbackData`
64+
will be set as ``callback_data``.
5965
6066
Warning:
6167
When setting ``run_async`` to :obj:`True`, you cannot rely on adding custom

telegram/ext/dictpersistence.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"""This module contains the DictPersistence class."""
2020
from copy import deepcopy
2121

22-
from typing import Any, DefaultDict, Dict, Optional, Tuple
22+
from typing import Any, DefaultDict, Dict, Optional, Tuple, cast
2323
from collections import defaultdict
2424

2525
from telegram.utils.helpers import (
@@ -135,7 +135,11 @@ def __init__(
135135
raise TypeError("bot_data_json must be serialized dict")
136136
if callback_data_json:
137137
try:
138-
self._callback_data = json.loads(callback_data_json)
138+
data = json.loads(callback_data_json)
139+
if data:
140+
self._callback_data = cast(CDCData, ([tuple(d) for d in data[0]], data[1]))
141+
else:
142+
self._callback_data = None
139143
self._callback_data_json = callback_data_json
140144
except (ValueError, AttributeError) as exc:
141145
raise TypeError(

tests/conftest.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import pytz
3131

3232
from telegram import (
33-
Bot,
3433
Message,
3534
User,
3635
Chat,
@@ -42,7 +41,7 @@
4241
PreCheckoutQuery,
4342
ChosenInlineResult,
4443
)
45-
from telegram.ext import Dispatcher, JobQueue, Updater, MessageFilter, Defaults, UpdateFilter
44+
from telegram.ext import Dispatcher, JobQueue, Updater, MessageFilter, Defaults, UpdateFilter, Bot
4645
from telegram.error import BadRequest
4746
from tests.bots import get_bot
4847

@@ -195,6 +194,9 @@ def pytest_configure(config):
195194

196195

197196
def make_bot(bot_info, **kwargs):
197+
"""
198+
Tests are executed on tg.ext.Bot, as that class only extends the functionality of tg.bot
199+
"""
198200
return Bot(bot_info['token'], private_key=PRIVATE_KEY, **kwargs)
199201

200202

tests/test_bot.py

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#
1717
# You should have received a copy of the GNU Lesser Public License
1818
# along with this program. If not, see [http://www.gnu.org/licenses/].
19-
import logging
2019
import time
2120
import datetime as dtm
2221
from pathlib import Path
@@ -49,7 +48,9 @@
4948
Chat,
5049
)
5150
from telegram.constants import MAX_INLINE_QUERY_RESULTS
51+
from telegram.ext import Bot as ExtBot
5252
from telegram.error import BadRequest, InvalidToken, NetworkError, RetryAfter
53+
from telegram.ext.utils.callbackdatacache import InvalidCallbackData
5354
from telegram.utils.helpers import (
5455
from_timestamp,
5556
escape_markdown,
@@ -103,6 +104,10 @@ def inline_results():
103104

104105

105106
class TestBot:
107+
"""
108+
Most are executed on tg.ext.Bot, as that class only extends the functionality of tg.bot
109+
"""
110+
106111
@pytest.mark.parametrize(
107112
'token',
108113
argvalues=[
@@ -124,7 +129,7 @@ def test_invalid_token(self, token):
124129
[(True, 1024, True), (False, 1024, False), (0, 0, True), (None, None, True)],
125130
)
126131
def test_callback_data_maxsize(self, bot, acd_in, maxsize, acd):
127-
bot = Bot(bot.token, arbitrary_callback_data=acd_in)
132+
bot = ExtBot(bot.token, arbitrary_callback_data=acd_in)
128133
assert bot.arbitrary_callback_data == acd
129134
assert bot.callback_data.maxsize == maxsize
130135

@@ -1110,7 +1115,7 @@ def test_get_updates(self, bot):
11101115
if updates:
11111116
assert isinstance(updates[0], Update)
11121117

1113-
def test_get_updates_invalid_callback_data(self, bot, monkeypatch, caplog):
1118+
def test_get_updates_invalid_callback_data(self, bot, monkeypatch):
11141119
def post(*args, **kwargs):
11151120
return [
11161121
Update(
@@ -1135,15 +1140,11 @@ def post(*args, **kwargs):
11351140
try:
11361141
monkeypatch.setattr(bot.request, 'post', post)
11371142
bot.delete_webhook() # make sure there is no webhook set if webhook tests failed
1138-
with caplog.at_level(logging.DEBUG):
1139-
updates = bot.get_updates(timeout=1)
1143+
updates = bot.get_updates(timeout=1)
11401144

1141-
assert any(
1142-
"Skipping CallbackQuery with invalid data: {'update_id': 17" in record.getMessage()
1143-
for record in caplog.records
1144-
)
11451145
assert isinstance(updates, list)
1146-
assert len(updates) == 0
1146+
assert len(updates) == 1
1147+
assert isinstance(updates[0].callback_query.data, InvalidCallbackData)
11471148

11481149
finally:
11491150
# Reset b/c bots scope is session
@@ -1881,10 +1882,15 @@ def test_replace_callback_data_send_message(self, bot, chat_id):
18811882

18821883
assert inline_keyboard[0][1] == no_replace_button
18831884
assert inline_keyboard[0][0] != replace_button
1884-
assert bot.callback_data.pop(inline_keyboard[0][0].callback_data) == 'replace_test'
1885+
keyboard, button = (
1886+
inline_keyboard[0][0].callback_data[:32],
1887+
inline_keyboard[0][0].callback_data[32:],
1888+
)
1889+
assert bot.callback_data._keyboard_data[keyboard].button_data[button] == 'replace_test'
18851890
finally:
18861891
bot.arbitrary_callback_data = False
1887-
bot.callback_data.clear()
1892+
bot.callback_data.clear_callback_data()
1893+
bot.callback_data.clear_callback_queries()
18881894

18891895
def test_replace_callback_data_stop_poll(self, bot, chat_id):
18901896
poll_message = bot.send_poll(chat_id=chat_id, question='test', options=['1', '2'])
@@ -1907,10 +1913,15 @@ def test_replace_callback_data_stop_poll(self, bot, chat_id):
19071913

19081914
assert inline_keyboard[0][1] == no_replace_button
19091915
assert inline_keyboard[0][0] != replace_button
1910-
assert bot.callback_data.pop(inline_keyboard[0][0].callback_data) == 'replace_test'
1916+
keyboard, button = (
1917+
inline_keyboard[0][0].callback_data[:32],
1918+
inline_keyboard[0][0].callback_data[32:],
1919+
)
1920+
assert bot.callback_data._keyboard_data[keyboard].button_data[button] == 'replace_test'
19111921
finally:
19121922
bot.arbitrary_callback_data = False
1913-
bot.callback_data.clear()
1923+
bot.callback_data.clear_callback_data()
1924+
bot.callback_data.clear_callback_queries()
19141925

19151926
def test_replace_callback_data_copy_message(self, bot, chat_id):
19161927
original_message = bot.send_message(chat_id=chat_id, text='original')
@@ -1932,13 +1943,15 @@ def test_replace_callback_data_copy_message(self, bot, chat_id):
19321943
)
19331944
message = helper_message.reply_to_message
19341945
inline_keyboard = message.reply_markup.inline_keyboard
1935-
1936-
assert inline_keyboard[0][1] == no_replace_button
1937-
assert inline_keyboard[0][0] != replace_button
1938-
assert bot.callback_data.pop(inline_keyboard[0][0].callback_data) == 'replace_test'
1946+
keyboard, button = (
1947+
inline_keyboard[0][0].callback_data[:32],
1948+
inline_keyboard[0][0].callback_data[32:],
1949+
)
1950+
assert bot.callback_data._keyboard_data[keyboard].button_data[button] == 'replace_test'
19391951
finally:
19401952
bot.arbitrary_callback_data = False
1941-
bot.callback_data.clear()
1953+
bot.callback_data.clear_callback_data()
1954+
bot.callback_data.clear_callback_queries()
19421955

19431956
# TODO: Needs improvement. We need incoming inline query to test answer.
19441957
def test_replace_callback_data_answer_inline_query(self, monkeypatch, bot, chat_id):
@@ -1954,8 +1967,12 @@ def make_assertion(
19541967
).inline_keyboard
19551968
assertion_1 = inline_keyboard[0][1] == no_replace_button
19561969
assertion_2 = inline_keyboard[0][0] != replace_button
1970+
keyboard, button = (
1971+
inline_keyboard[0][0].callback_data[:32],
1972+
inline_keyboard[0][0].callback_data[32:],
1973+
)
19571974
assertion_3 = (
1958-
bot.callback_data.pop(inline_keyboard[0][0].callback_data) == 'replace_test'
1975+
bot.callback_data._keyboard_data[keyboard].button_data[button] == 'replace_test'
19591976
)
19601977
return assertion_1 and assertion_2 and assertion_3
19611978

@@ -1984,4 +2001,5 @@ def make_assertion(
19842001

19852002
finally:
19862003
bot.arbitrary_callback_data = False
1987-
bot.callback_data.clear()
2004+
bot.callback_data.clear_callback_data()
2005+
bot.callback_data.clear_callback_queries()

tests/test_callbackquery.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import pytest
2121

2222
from telegram import CallbackQuery, User, Message, Chat, Audio, Bot
23-
from telegram.error import InvalidCallbackData
2423
from tests.conftest import check_shortcut_signature, check_shortcut_call
2524

2625

@@ -83,29 +82,6 @@ def test_de_json(self, bot):
8382
assert callback_query.inline_message_id == self.inline_message_id
8483
assert callback_query.game_short_name == self.game_short_name
8584

86-
def test_de_json_arbitrary_callback_data(self, bot):
87-
bot.arbitrary_callback_data = True
88-
try:
89-
bot.callback_data.clear()
90-
bot.callback_data._data['callback_data'] = (0, 'test')
91-
bot.callback_data._deque.appendleft('callback_data')
92-
json_dict = {
93-
'id': self.id_,
94-
'from': self.from_user.to_dict(),
95-
'chat_instance': self.chat_instance,
96-
'message': self.message.to_dict(),
97-
'data': 'callback_data',
98-
'inline_message_id': self.inline_message_id,
99-
'game_short_name': self.game_short_name,
100-
'default_quote': True,
101-
}
102-
assert CallbackQuery.de_json(json_dict, bot).data == 'test'
103-
with pytest.raises(InvalidCallbackData):
104-
CallbackQuery.de_json(json_dict, bot)
105-
finally:
106-
bot.arbitrary_callback_data = False
107-
bot.callback_data.clear()
108-
10985
def test_to_dict(self, callback_query):
11086
callback_query_dict = callback_query.to_dict()
11187

tests/test_error.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
ChatMigrated,
3232
RetryAfter,
3333
Conflict,
34-
InvalidCallbackData,
3534
)
35+
from telegram.ext.utils.callbackdatacache import InvalidCallbackData
3636

3737

3838
class TestErrors:
@@ -113,7 +113,6 @@ def test_conflict(self):
113113
(RetryAfter(12), ["message", "retry_after"]),
114114
(Conflict("test message"), ["message"]),
115115
(TelegramDecryptionError("test message"), ["message"]),
116-
(InvalidCallbackData(789), ['update_id']),
117116
],
118117
)
119118
def test_errors_pickling(self, exception, attributes):

tests/test_inlinekeyboardmarkup.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -136,22 +136,6 @@ def test_de_json(self):
136136
assert keyboard[0][0].text == 'start'
137137
assert keyboard[0][0].url == 'http://google.com'
138138

139-
def test_replace_callback_data(self, bot):
140-
try:
141-
button_1 = InlineKeyboardButton(text='no_callback_data', url='http://google.com')
142-
obj = {1: 'test'}
143-
button_2 = InlineKeyboardButton(text='callback_data', callback_data=obj)
144-
keyboard = InlineKeyboardMarkup([[button_1, button_2]])
145-
146-
parsed_keyboard = keyboard.replace_callback_data(bot=bot)
147-
assert parsed_keyboard.inline_keyboard[0][0] is button_1
148-
assert parsed_keyboard.inline_keyboard[0][1] is not button_2
149-
assert parsed_keyboard.inline_keyboard[0][1].text == button_2.text
150-
uuid = parsed_keyboard.inline_keyboard[0][1].callback_data
151-
assert bot.callback_data.pop(uuid=uuid) is obj
152-
finally:
153-
bot.callback_data.clear()
154-
155139
def test_equality(self):
156140
a = InlineKeyboardMarkup.from_column(
157141
[

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

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

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy