New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Persistence #1017
Persistence #1017
Conversation
Add tests for Basepersistence
For Py2 compatibility
@Eldinnie Is this ready for review? Did we discuss it in the chat and I just forgot about it? |
Hi @SehgalDivij, this is an implementation that will generally solve the persistence for ptb. An abstract base class was provided that will allow users to implement their own serialization interfaces and pass them on to the library, effectively giving you the ability to serialize almost every collection in the library. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding some comments, mostly relating to the overall implementation. I have not yet read the code through thoroughly :)
telegram/ext/basepersistence.py
Outdated
Attributes: | ||
store_user_data (:obj:`bool`): Optional, Whether user_data should be saved by this | ||
persistence class. | ||
store_chat_data (:obj:`bool`): Optional. Whether user_data should be saved by this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chat_data*
telegram/ext/basepersistence.py
Outdated
Args: | ||
store_user_data (:obj:`bool`, optional): Whether user_data should be saved by this | ||
persistence class. Default is ``True``. | ||
store_chat_data (:obj:`bool`, optional): Whether user_data should be saved by this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chat_data*
telegram/ext/basepersistence.py
Outdated
persistence a chance to finish up saving or close a database connection gracefully. If this | ||
is not of any importance just pass will be sufficient. | ||
""" | ||
raise NotImplementedError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is not of importance, should it really raise NYE?
telegram/ext/conversationhandler.py
Outdated
@@ -76,6 +76,10 @@ class ConversationHandler(Handler): | |||
per_user (:obj:`bool`): Optional. If the conversationkey should contain the User's ID. | |||
per_message (:obj:`bool`): Optional. If the conversationkey should contain the Message's | |||
ID. | |||
name (:obj:`str`): Optional. The name for this conversationhandler. Required for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we default to an internal counter or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would rely on the conv_handlers keeping in the same order when the code is changing. Better to force naming IMO
telegram/ext/conversationhandler.py
Outdated
@@ -76,6 +76,10 @@ class ConversationHandler(Handler): | |||
per_user (:obj:`bool`): Optional. If the conversationkey should contain the User's ID. | |||
per_message (:obj:`bool`): Optional. If the conversationkey should contain the Message's | |||
ID. | |||
name (:obj:`str`): Optional. The name for this conversationhandler. Required for | |||
persistence | |||
persistent (:obj:`bool`): Optional. If the conversations dict for this handler should be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If name is required, could we not just have a single persistent_name
that turns persistence on if a string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. But this way we also have the name seperate if not persistent. Might be usefull some day?
telegram/ext/dispatcher.py
Outdated
if self.persistence.store_chat_data: | ||
self.chat_data = self.persistence.get_chat_data() | ||
if not isinstance(self.chat_data, defaultdict): | ||
raise ValueError("`chat_data must be of type defaultdict") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
misplaced `
from telegram.ext import BasePersistence | ||
|
||
|
||
class PicklePersistence(BasePersistence): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there ever a file where it makes sense to use single_file=False?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dunno, but it might
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really a fan of having features that we aren't sure anyone can use... It's just more maintenance work for us :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also you can't choose the filetype (suffix) when using single_file=False.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but I don;t really see a problem here. I think it's versatile enough this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more comments, but otherwise I think this is probably good to go. Do we wanna merge it after or before #1100 ?
telegram/ext/updater.py
Outdated
@@ -485,6 +492,8 @@ def _join_threads(self): | |||
|
|||
def signal_handler(self, signum, frame): | |||
self.is_idle = False | |||
if self.persistence: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be moved into the if self.running:
block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cause otherwise we impede the ability to exit immediately? Like if the user presses CTRL-C (or whatever) twice, it shouldn't save persistence twice, it just quit ASAP imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point
telegram/ext/dispatcher.py
Outdated
else: | ||
self.persistence = None | ||
|
||
if self.persistence: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this block isn't just in the if persistence:
block above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there was no good one
Ok for future reference (And for the future
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks brilliant!
I added a few comments with some suggestions and questions in places where I got a bit confused.
The only quib I really have implementation-wise, is that Persistence.update_* all receive the entire defaultdict, instead of only the changed part, but I'm not sure if there is really a good way to change this. The reason I'd want this btw, is that if you were to create a DB backend like mysql or redis or whatever, then that's probably what you'd want.
telegram/ext/basepersistence.py
Outdated
:meth:`update_user_data`. | ||
* If you want to store conversation data with :class:`telegram.ext.ConversationHandler`, you | ||
must overwrite :meth:`get_conversations` and :meth:`update_conversations`. | ||
* :meth:`flush` will be called when the bot is shutdown, and must always be overwritten. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This docstring should probably be changed, since flush mustn't always be overwritten as it is implemented atm (which I think is a good thing)
telegram/ext/dispatcher.py
Outdated
""":obj:`dict`: A dictionary handlers can use to store data for the chat.""" | ||
if persistence: | ||
if not isinstance(persistence, BasePersistence): | ||
self.logger.warning("persistence should be based on telegram.ext.BasePersistence") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo this should raise an exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that. But if someone really wants to create their own version without basing it on Basepersistence they should be allowed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I equate it to how we handle handlers in dispatche https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/dispatcher.py#L329
Also BaseFilter iirc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok seems legit
from telegram.ext import BasePersistence | ||
|
||
|
||
class PicklePersistence(BasePersistence): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really a fan of having features that we aren't sure anyone can use... It's just more maintenance work for us :/
from telegram.ext import BasePersistence | ||
|
||
|
||
class PicklePersistence(BasePersistence): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also you can't choose the filetype (suffix) when using single_file=False.?
u = Updater(bot=bot, persistence=pickle_persistence_2) | ||
dp = u.dispatcher | ||
dp.add_handler(h2) | ||
dp.process_update(update) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check to make sure that first and second even got called?
As discussed with @jsmnbom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add some help to the wiki shortly after merge.
Maybe even an example?
Overall really amazing work @Eldinnie ! :D
Already using PTB 11.1.0 but my script gives error when trying to import BasePersistence fromtelegram.ext. |
@owneroxxor it's merged into master, but not yet released. In the next released version it will be available. |
@Eldinnie when do you release this feature? we need this! |
Also would like a release! I guess for the meantime we can install from master. |
Adding a construct for adding persistence to PTB.