-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Context #1100
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
Conversation
The design discussion is at #1026 |
This is a bit different from that discussion. Mainly that everything is in the context object, but that it acts like a update object, so it's still very convenient for the user. (it also made it much easier to do backwards compat, since it's a different amount of parameters) |
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 looks much better, but I'm afraid we'll still need another pass, hopefully the last. See my comments on the code.
Regarding the "user facing strings" (docstring, deprecation warnings & changelog) - once we'll get a version of the code we're all happy with, I'll add a commit with text (and then you can scrutinize me, lol ;-) )
telegram/ext/dispatcher.py
Outdated
handler.handle_update(update, self) | ||
for handler in self.handlers[group]: | ||
check = handler.check_update(update) | ||
if check is not None and check is not 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.
As discussed, I find this semantics confusing. I prefer something more straight forward:
bool(checkl)
evaluates to False
- don't handle the update.
bool(check)
evaluates to True
- handle the update and pass check
to handle_update()
.
However, if you can describe the semantics you chose in simple English and a short phrase (and preferably with docstrings type annotations which makes sense) we can consider your 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.
Current behaviour I've described as:
Either ``None`` or ``False`` if the update should not be handled. Otherwise an object that will be passed to :attr:`handle_update` and :attr:`collect_additional_context` when the update gets handled.
This allows both stuff like having CommandHandle.check_update()
return message.text.split()[1:]
when the update should be handled, and even if there are no args, and it therefore returns []
(a falsey value) it will be handled.
This would advokate for having it just be: Either None to not handle or something else to handle.
But for example in MessageHandler.check_update()
I have a return self.filters(message)
which determines if the update should be handled.
In conclusion I think we should keep the current logic. Or if you really wanna simplify it, then have it be None to not handle, and everything else gets handled (so the first scenario is still supported).
telegram/ext/handler.py
Outdated
@@ -63,12 +78,25 @@ def __init__(self, | |||
pass_update_queue=False, | |||
pass_job_queue=False, | |||
pass_user_data=False, | |||
pass_chat_data=False): | |||
pass_chat_data=False, | |||
use_context=None): |
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 put a (very short) deadline for use_context=None
and move to an extra deprecation period with use_context=True
.
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.
So how long do you propose to have this default to old handler semantics (with deprecation warning obviously) and how long do you think we should keep backward compatibility code once we change the default to the new handler semantics?
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 would say 2 months for both?
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.
1 month for each of them seems fine to me... or is that what you're suggesting too?
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.
Maybe: Next major version (so if this is going to be v11, then on v12 we change the default to True, and on v13 or v14 we'll remove the backward compatibility code)
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.
Sounds good to me
(pycharm can be an arse sometimes)
Replying to @Eldinnie review: 1.2. MessageHandler for everything else. PrefixHandler should be a convenience wrapper on top of it. 1.3. What is wrong with list of filters? I do not recall that conversation. 2.1. *_updates should still exist in MessageHandler.init() prototype. The implementation detail of using filters is a very good idea. 2.2. I would keep RegexHandler, but change it to be a convinient wrapper on top of MessageHandler. |
1.3 Long time ago the filters argument was supposed to be a list of callables and the handler woud handle the update if any of those would return True In october 2016 the bitwise filters have been added #411 and we've supported both (list of filters and bitwise filters) since then. there's a warning list is deprecated since then: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/messagehandler.py#L123 |
1.3. Ok. Removing the filters list is a good idea. But I think that we should have in the migration guide a code snippet demonstrating how to convert a list of filters to bitwise-or filters |
Could we please gather up the individual user handlers that do not fit the new callback signature and show a single deprecation warning message to the user in the following fashion:
Might be possible to do this with a little timeout that checks a list of wrongdoings after like 2 seconds or so after the initialization step. Reasoning behind this is that I'm currently being flooded with ~140 warning messages in one of my bigger bots, and we don't want to make a bad impression towards our users with this change but the opposite :) |
@JosXa Lets first see what the actual strings will look like.
|
examples/paymentbot.py
Outdated
query = update.shipping_query | ||
# check the payload, is this from your bot? | ||
if query.invoice_payload != 'Custom-Payload': | ||
# answer False pre_checkout_query | ||
bot.answer_shipping_query(shipping_query_id=query.id, ok=False, | ||
error_message="Something went wrong...") | ||
query.answer(shipping_query_id=query.id, ok=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.
Remove shipping_query_id=query.id,
.
examples/paymentbot.py
Outdated
@@ -89,31 +90,33 @@ def shipping_callback(bot, update): | |||
# an array of LabeledPrice objects | |||
price_list = [LabeledPrice('B1', 150), LabeledPrice('B2', 200)] | |||
options.append(ShippingOption('2', 'Shipping Option B', price_list)) | |||
bot.answer_shipping_query(shipping_query_id=query.id, ok=True, | |||
shipping_options=options) | |||
query.answer(shipping_query_id=query.id, ok=True, |
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.
Remove shipping_query_id=query.id,
.
examples/paymentbot.py
Outdated
query = update.pre_checkout_query | ||
# check the payload, is this from your bot? | ||
if query.invoice_payload != 'Custom-Payload': | ||
# answer False pre_checkout_query | ||
bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=False, | ||
error_message="Something went wrong...") | ||
query.answer(pre_checkout_query_id=query.id, ok=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.
Remove pre_checkout_query_id=query.id,
.
examples/paymentbot.py
Outdated
else: | ||
bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=True) | ||
query.answer(pre_checkout_query_id=query.id, ok=True) |
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.
Remove pre_checkout_query_id=query.id,
.
telegram/ext/messagehandler.py
Outdated
optional_args = self.collect_optional_args(dispatcher, update) | ||
|
||
return self.callback(dispatcher.bot, update, **optional_args) | ||
if self.filters is None: |
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.
self.filters will never be None if it evaluated to True on line 149.
telegram/ext/jobqueue.py
Outdated
self.use_context = False | ||
|
||
self._dispatcher = MockDispatcher() | ||
self._dispatcher = None |
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 clobbers lines 50-59, maybe reorder or:
if bot:
...
self._dispatcher = MockDispatcher()
! else:
! self._dispatcher = None
Thanks for the review @nmlorg :D You're totally right in all the comments :) |
This reverts commit 247577b.
This adds optional support for using context objects instead of all the pass_* in the handlers, as we've talked about a lot in the past.
Motivation is #1080 being seemingly really difficult to implement nicely, and it seems redundant if this got implemented instead (therefore closes #1080).
Not sure if this is exactly how we talked about it, but it seems to implement all that's needed (and as a bonus is 100% backwards compatible!!).
Currently employs a bit of magic to figure out whether to use the old pass_ or the new context. Namely it checks the
callback
signature to check how many parameters it expects. This is expected to work very well on python >= 3.5 even with decorators. On python < 3.5 it will fail completely if decorators are used, but otherwise work fine.The user can disable the new functionality by setting
use_context=False
in a given handler. This is also how it can be manually turned on, in the case of python < 3.5 and decorated callback functions.