Skip to content

Commit b388d1a

Browse files
committed
Implemented test for base class Handler and fixed order of instructions in handler.py
1 parent 05c16a1 commit b388d1a

File tree

2 files changed

+149
-25
lines changed

2 files changed

+149
-25
lines changed

telegram/ext/handler.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def __init__(self,
8787
self.pass_chat_data = pass_chat_data
8888
self._autowire_initialized = False
8989
self._callback_args = None
90+
self._passable = None
9091

9192
def check_update(self, update):
9293
"""
@@ -119,13 +120,13 @@ def handle_update(self, update, dispatcher):
119120

120121
def __warn_autowire(self):
121122
""" Warn if the user has set any `pass_*` flags to True in addition to `autowire` """
122-
for flag in self.__get_available_pass_flags():
123+
for flag in self._get_available_pass_flags():
123124
to_pass = bool(getattr(self, flag))
124125
if to_pass is True:
125126
warnings.warn('If `autowire` is set to `True`, it is unnecessary '
126127
'to provide the `{}` flag.'.format(flag))
127128

128-
def __get_available_pass_flags(self):
129+
def _get_available_pass_flags(self):
129130
"""
130131
Used to provide warnings if the user decides to use `autowire` in conjunction with
131132
``pass_*`` flags, and to recalculate all flags.
@@ -136,6 +137,20 @@ def __get_available_pass_flags(self):
136137
"""
137138
return [f for f in dir(self) if f.startswith('pass_')]
138139

140+
def __should_pass_obj(self, name):
141+
"""
142+
Utility to determine whether a passable object is part of
143+
the user handler's signature, makes sense in this context,
144+
and is not explicitly set to `False`.
145+
"""
146+
all_passable_objects = {'update_queue', 'job_queue', 'user_data', 'chat_data', 'args', 'groups', 'groupdict'}
147+
is_requested = name in all_passable_objects and name in self._callback_args
148+
if is_requested and name not in self._passable:
149+
warnings.warn("The argument `{}` cannot be autowired since it is not available "
150+
"on `{}s`.".format(name, type(self).__name__))
151+
return False
152+
return is_requested
153+
139154
def set_autowired_flags(self, passable={'update_queue', 'job_queue', 'user_data', 'chat_data'}):
140155
"""
141156
This method inspects the callback handler for used arguments. If it finds arguments that
@@ -148,47 +163,34 @@ def set_autowired_flags(self, passable={'update_queue', 'job_queue', 'user_data'
148163
The ``passable`` arguments are required to be explicit as opposed to dynamically generated
149164
to be absolutely safe that no arguments will be passed that are not allowed.
150165
"""
166+
self._passable = passable
151167

152168
if not self.autowire:
153169
raise ValueError("This handler is not autowired.")
154-
self.__warn_autowire()
155170

156171
if self._autowire_initialized:
157172
# In case that users decide to change their callback signatures at runtime, give the
158173
# possibility to recalculate all flags.
159-
for flag in self.__get_available_pass_flags():
174+
for flag in self._get_available_pass_flags():
160175
setattr(self, flag, False)
161176

162-
all_passable_objects = {'update_queue', 'job_queue', 'user_data', 'chat_data', 'args', 'groups', 'groupdict'}
177+
self.__warn_autowire()
163178

164179
self._callback_args = inspect_arguments(self.callback)
165180

166-
def should_pass_obj(name):
167-
"""
168-
Utility to determine whether a passable object is part of
169-
the user handler's signature, makes sense in this context,
170-
and is not explicitly set to `False`.
171-
"""
172-
is_requested = name in all_passable_objects and name in self._callback_args
173-
if is_requested and name not in passable:
174-
warnings.warn("The argument `{}` cannot be autowired since it is not available "
175-
"on `{}s`.".format(name, type(self).__name__))
176-
return False
177-
return is_requested
178-
179-
if should_pass_obj('update_queue'):
181+
if self.__should_pass_obj('update_queue'):
180182
self.pass_update_queue = True
181-
if should_pass_obj('job_queue'):
183+
if self.__should_pass_obj('job_queue'):
182184
self.pass_job_queue = True
183-
if should_pass_obj('user_data'):
185+
if self.__should_pass_obj('user_data'):
184186
self.pass_user_data = True
185-
if should_pass_obj('chat_data'):
187+
if self.__should_pass_obj('chat_data'):
186188
self.pass_chat_data = True
187-
if should_pass_obj('args'):
189+
if self.__should_pass_obj('args'):
188190
self.pass_args = True
189-
if should_pass_obj('groups'):
191+
if self.__should_pass_obj('groups'):
190192
self.pass_groups = True
191-
if should_pass_obj('groupdict'):
193+
if self.__should_pass_obj('groupdict'):
192194
self.pass_groupdict = True
193195

194196
self._autowire_initialized = True

tests/test_handler.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env python
2+
#
3+
# A library that provides a Python interface to the Telegram Bot API
4+
# Copyright (C) 2015-2017
5+
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser Public License
18+
# along with this program. If not, see [http://www.gnu.org/licenses/].
19+
20+
import pytest
21+
22+
from telegram.ext import Handler
23+
24+
25+
class TestHandler(object):
26+
test_flag = False
27+
28+
@pytest.fixture(autouse=True)
29+
def reset(self):
30+
self.test_flag = False
31+
32+
def callback_basic(self, bot, update):
33+
pass
34+
35+
def callback_some_passable(self, bot, update, update_queue, chat_data):
36+
pass
37+
38+
def callback_all_passable(self, bot, update, update_queue, job_queue, chat_data, user_data):
39+
pass
40+
41+
def test_set_autowired_flags_all(self):
42+
handler = Handler(self.callback_all_passable, autowire=True)
43+
assert handler._autowire_initialized is False
44+
assert handler.pass_update_queue is False
45+
assert handler.pass_job_queue is False
46+
assert handler.pass_chat_data is False
47+
assert handler.pass_user_data is False
48+
49+
handler.set_autowired_flags()
50+
51+
assert handler._autowire_initialized is True
52+
assert handler.pass_update_queue is True
53+
assert handler.pass_job_queue is True
54+
assert handler.pass_chat_data is True
55+
assert handler.pass_user_data is True
56+
57+
def test_set_autowired_flags_some(self):
58+
handler = Handler(self.callback_some_passable, autowire=True)
59+
assert handler.pass_update_queue is False
60+
assert handler.pass_chat_data is False
61+
62+
handler.set_autowired_flags()
63+
64+
assert handler._autowire_initialized is True
65+
assert handler.pass_update_queue is True
66+
assert handler.pass_chat_data is True
67+
68+
def test_set_autowired_flags_wrong(self):
69+
handler = Handler(self.callback_all_passable, autowire=True)
70+
with pytest.raises(UserWarning):
71+
handler.set_autowired_flags({'kektus'})
72+
with pytest.raises(UserWarning):
73+
handler.set_autowired_flags({'chat_data', 'kektus'})
74+
with pytest.raises(UserWarning):
75+
handler.set_autowired_flags({'bot', 'update'})
76+
77+
def test_autowire_and_pass(self):
78+
handler = Handler(self.callback_all_passable, autowire=True, pass_chat_data=True)
79+
with pytest.raises(UserWarning):
80+
handler.set_autowired_flags()
81+
82+
def test_not_autowired_set_flags(self):
83+
handler = Handler(self.callback_all_passable, autowire=False)
84+
with pytest.raises(ValueError):
85+
handler.set_autowired_flags()
86+
87+
def test_autowire_reinitialize(self):
88+
handler = Handler(self.callback_all_passable, autowire=True)
89+
assert handler._autowire_initialized is False
90+
assert handler.pass_update_queue is False
91+
assert handler.pass_job_queue is False
92+
assert handler.pass_chat_data is False
93+
assert handler.pass_user_data is False
94+
95+
handler.set_autowired_flags()
96+
97+
assert handler._autowire_initialized is True
98+
assert handler.pass_update_queue is True
99+
assert handler.pass_job_queue is True
100+
assert handler.pass_chat_data is True
101+
assert handler.pass_user_data is True
102+
103+
handler.callback = self.callback_some_passable
104+
handler.set_autowired_flags()
105+
106+
assert handler._autowire_initialized is True
107+
assert handler.pass_update_queue is True
108+
assert handler.pass_job_queue is False
109+
assert handler.pass_chat_data is True
110+
assert handler.pass_user_data is False
111+
112+
def test_get_available_pass_flags(self):
113+
handler = Handler(self.callback_all_passable, autowire=True)
114+
assert handler.pass_update_queue is False
115+
assert handler.pass_job_queue is False
116+
assert handler.pass_chat_data is False
117+
assert handler.pass_user_data is False
118+
119+
handler.set_autowired_flags()
120+
121+
assert set(handler._get_available_pass_flags()) == {'pass_update_queue', 'pass_job_queue', 'pass_chat_data',
122+
'pass_user_data'}

0 commit comments

Comments
 (0)