Skip to content

Commit ecf88fe

Browse files
committed
Finish up BasePersistence and implementation
1 parent f7e81b9 commit ecf88fe

File tree

4 files changed

+72
-17
lines changed

4 files changed

+72
-17
lines changed

telegram/ext/basepersistence.py

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,61 @@
2020

2121

2222
class BasePersistence(object):
23+
"""Example class for adding persistence to your bot.
24+
Subclass this object for different implementations of a persistent bot.
25+
26+
All relevant methods must be overwritten. This means:
27+
* If :attr:`store_chat_data` is ``True`` you must overwrite :attr:`get_chat_data` and
28+
:attr:`update_chat_data`
29+
* If :attr:`store_user_data` is ``True`` you must overwrite :attr:`get_user_data` and
30+
:attr:`update_user_data`
31+
* If you want to store conversation data with :class:`telegram.ext.CanversationHandler`, you
32+
must overwrite :attr:`get_conversations` and :attr:`update_conversations`
33+
* :attr:`flush` will be called when the bot is shutdown, and must always be overwritten.
34+
35+
Attributes:
36+
store_user_data (:obj:`bool`): Whether user_data should be saved by this
37+
persistence class.
38+
store_chat_data (:obj:`bool`): Whether user_data should be saved by this
39+
persistence class
40+
41+
Args:
42+
store_user_data (:obj:`bool`): Whether user_data should be saved by this
43+
persistence class.
44+
store_chat_data (:obj:`bool`): Whether user_data should be saved by this
45+
persistence class
46+
"""
47+
2348
def __init__(self, store_user_data=False, store_chat_data=False):
24-
"""
25-
Args:
26-
store_user_data (:obj:`bool`): Whether user_data should be saved by this
27-
persistence class.
28-
store_chat_data (:obj:`bool`): Whether user_data should be saved by this
29-
persistence class
30-
"""
3149
self.store_user_data = store_user_data
3250
self.store_chat_data = store_chat_data
3351

3452
def get_user_data(self):
35-
""""
53+
""""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
54+
persistence object. It should return the user_data if stored, or an empty
55+
``defaultdict(dict)``.
56+
3657
Returns:
3758
:obj:'defaultdict`: The restored user data.
3859
"""
3960
raise NotImplementedError
4061

4162
def get_chat_data(self):
42-
""""
63+
""""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
64+
persistence object. It should return the chat_data if stored, or an empty
65+
``defaultdict(dict)``.
66+
4367
Returns:
4468
:obj:'defaultdict`: The restored chat data.
4569
"""
4670
raise NotImplementedError
4771

4872
def get_conversations(self, name):
49-
""""
73+
""""Will be called by :class:`telegram.ext.Dispatcher` when a
74+
:class:`telegram.ext.CanversationHandler` is added if
75+
:attr:`telegram.ext.ConversationHandler.persistent` is ``True``.
76+
It should return the conversations for the handler with `name` or an empty ``dict``
77+
5078
Args:
5179
name (:obj:`str`): The handlers name.
5280
@@ -55,29 +83,40 @@ def get_conversations(self, name):
5583
"""
5684
raise NotImplementedError
5785

58-
def update_conversation(self, conversations):
59-
""""
86+
def update_conversations(self, name, conversations):
87+
""""Will be called when a :attr:`telegram.ext.ConversationHandler.update_state`
88+
is called. this allows the storeage of the new state in the persistence.
89+
6090
Args:
91+
name (:obj:`str`): The handlers name.
6192
conversation (:obj:'dict`): The :attr:`telegram.ext.ConversationHandler.conversations`
6293
dict to store.
6394
"""
6495
raise NotImplementedError
6596

6697
def update_user_data(self, user_data):
67-
""""
98+
""""Will be calle by the :class:`telegram.ext.Dispatcher` after a handler has
99+
handled an update. It will be the :attr:`telegram.ext.Dispatcher.user_data` defaultdict.
100+
68101
Args:
69102
user_data (:obj:'defaultdict`): The :attr:`telegram.ext.dispatcher.user_data`
70103
defaultdict to store.
71104
"""
72105
raise NotImplementedError
73106

74107
def update_chat_data(self, chat_data):
75-
""""
108+
""""Will be calle by the :class:`telegram.ext.Dispatcher` after a handler has
109+
handled an update. It will be the :attr:`telegram.ext.Dispatcher.chat_data` defaultdict.
110+
76111
Args:
77112
chat_data (:obj:'defaultdict`): The :attr:`telegram.ext.dispatcher.chat_data`
78113
defaultdict to store.
79114
"""
80115
raise NotImplementedError
81116

82117
def flush(self):
118+
"""Will be called by :class:`telegram.ext.Updater` upon receiving a stop signal. Gives the
119+
persistence a chance to finish up saving or close a database connection gracefully. If this
120+
is not of any importance just pass will be sufficient.
121+
"""
83122
raise NotImplementedError

telegram/ext/conversationhandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,4 @@ def update_state(self, new_state, key):
328328
self.conversations[key] = new_state
329329

330330
if self.persistent:
331-
self.persistence.update_conversation(self.conversations)
331+
self.persistence.update_conversations(self.name, self.conversations)

telegram/ext/updater.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,8 @@ def _join_threads(self):
459459

460460
def signal_handler(self, signum, frame):
461461
self.is_idle = False
462+
if self.persistence:
463+
self.persistence.flush()
462464
if self.running:
463465
self.logger.info('Received signal {} ({}), stopping...'.format(
464466
signum, get_signal_name(signum)))
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_creation(self, base_persistence):
6666
with pytest.raises(NotImplementedError):
6767
base_persistence.update_user_data(None)
6868
with pytest.raises(NotImplementedError):
69-
base_persistence.update_conversation(None)
69+
base_persistence.update_conversations(None)
7070
with pytest.raises(NotImplementedError):
7171
base_persistence.flush()
7272

@@ -166,14 +166,28 @@ def callback_unknown_user_or_chat(bot, update, user_data, chat_data):
166166
rec = caplog.records[-2]
167167
assert rec.msg == 'Saving chat data raised an error'
168168
assert rec.levelname == 'ERROR'
169-
170169
m.from_user = user2
171170
m.chat = chat1
172171
u = Update(1, m)
173172
dp.process_update(u)
174173
m.chat = chat2
175174
u = Update(2, m)
175+
176+
def save_chat_data(data):
177+
if -987654 not in data:
178+
pytest.fail()
179+
180+
def save_user_data(data):
181+
if 54321 not in data:
182+
pytest.fail()
183+
184+
base_persistence.update_chat_data = save_chat_data
185+
base_persistence.update_user_data = save_user_data
176186
dp.process_update(u)
177187

178188
assert dp.user_data[54321][1] == 'test7'
179189
assert dp.chat_data[-987654][2] == 'test8'
190+
191+
def test_flush(self, updater):
192+
with pytest.raises(NotImplementedError):
193+
updater.signal_handler(None, None)

0 commit comments

Comments
 (0)