- Notifications
You must be signed in to change notification settings - Fork5.7k
Add default values#1490
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Add default values#1490
Uh oh!
There was an error while loading.Please reload this page.
Conversation
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 didnt check the tests because I feel nowhere save with them.
@property | ||
def _has_input_message_content(self): | ||
return hasattr(self, 'input_message_content') |
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 dont exactly see what this has to do with the PR?
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 question … Don't recall, why I added it …
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.
Mh, actually it seems that theInlineQueryResult…
classes don't always have aninput_message_content
attribute. This is due to the fact, that the base classInlineQueryResult
doesn't have one and in the child classes the optionals are parsed in the manner
if input_message_content: self.input_message_content = input_message_content
without precedingself.input_message_content = None
.
I.e. if the optionalinput_message_content
is not passed, the class instance won't have such an attribute.
I'm not sure that this is acutally wanted behavior, but changing that would surely be the content of another PR …
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.
Okay, above mentioned issue is solved by#1600. But this is still needed, since e.g.InlineQueryResultGame
hasneither aparse_mode
nor arinput_message_content
attribute.
Poolitzer commentedOct 10, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
What I saw from my little dive into your changes is that this is a good solutions which tackels all the problems we had, everything is covered. If the other maintainer agree, we can built the other default ideas we had (timeout, disable web preview mainly) on top of this. Lets use#1527 to track this if we come so far. Good job though, I really like this :) Since this is such a big change and I bet that there will be a lot of discussion around this, I feel like we should give it it's own version, so I added it to the 12.3 milestone. |
Hey, I was wondering if it was possible to move this check: from all the different so that we wouldn't have as much code duplication. |
jh0ker commentedOct 11, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Regarding the Assuming we want to be able to have defaults for other parameters, I suggest a classDefaults():def__init__(parse_mode=None,disable_notification=False):self.parse_mode=parse_modeself.disable_notification=disable_notification Then, we can use it like this: defBot(token,base_url=None,base_file_url=None,request=None,private_key=None,private_key_password=None,defaults=Defaults()):classBot(TelegramObject): [...]@logdefsend_message(self,chat_id,text,parse_mode=defaults.parse_mode,disable_web_page_preview=None,disable_notification=defaults.disable_notification,reply_to_message_id=None,reply_markup=None,timeout=None,**kwargs): [...]returnBot(token,base_url,base_file_url,request,private_key,private_key_password) which means you can create a bot like Now, i realize this seems a little janky with the factory and all, but i still wanted to put it out there as an idea. |
Bibo-Joshi commentedOct 15, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Your idea for a My main concern is usability. To me it seems a bit harder to understand
than
Still, I guess I'd put maintainability before usability 😄 |
jsmnbom commentedOct 15, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Here's a solution that does the best of both worlds (maybe?) importfunctoolsimportinspectclassDefaults:parse_mode=Nonedisable_notification=FalseclassBot:def__new__(cls,*args,**kwargs):# Transform default_x=y kwargs into Defaults.x=ydefaults=Defaults()forkwarginlist(kwargs.keys()):ifkwarg.startswith('default_'):defaults.__dict__[kwarg[8:]]=kwargs[kwarg]delkwargs[kwarg]# Make an instance of the classinstance=super(Bot,cls).__new__(cls,*args,**kwargs)# For each methodformethod_name,methodininspect.getmembers(instance,predicate=inspect.ismethod):# Get kwargsargspec=inspect.getfullargspec(method)kwarg_names=argspec.args[-len(argspec.defaultsor []):]# Check if Defaults has a attribute that matches the kwarg nameneeds_default= [kwarg_nameforkwarg_nameinkwarg_namesifkwarg_nameindefaults.__dict__.keys()]# Make a dict of kwarg name and the default valuedefault_kwargs= {kwarg_name:defaults.__dict__[kwarg_name]forkwarg_nameinneeds_default}# Apply the defaults using a partialifdefault_kwargs:setattr(instance,method_name,functools.partial(method,**default_kwargs))returninstancedef__init__(self,*args,**kwargs):passdeftest(self,parse_mode=None,disable_notification=False):print('parse_mode=',parse_mode,' ','disable_notification=',disable_notification)print('bot1')# bot1bot1=Bot()bot1.test()# parse_mode= None disable_notification= Falsebot1.test(parse_mode='md')# parse_mode= md disable_notification= Falsebot1.test(parse_mode='html')# parse_mode= html disable_notification= Falsebot1.test(parse_mode=None)# parse_mode= None disable_notification= Falsebot1.test(disable_notification=False)# parse_mode= None disable_notification= Falsebot1.test(disable_notification=None)# parse_mode= None disable_notification= Nonebot1.test(disable_notification=True)# parse_mode= None disable_notification= Trueprint('bot2')# bot2bot2=Bot(default_parse_mode='md')bot2.test()# parse_mode= md disable_notification= Falsebot2.test(parse_mode='md')# parse_mode= md disable_notification= Falsebot2.test(parse_mode='html')# parse_mode= html disable_notification= Falsebot2.test(parse_mode=None)# parse_mode= None disable_notification= Falsebot2.test(disable_notification=False)# parse_mode= md disable_notification= Falsebot2.test(disable_notification=None)# parse_mode= md disable_notification= Nonebot2.test(disable_notification=True)# parse_mode= md disable_notification= True |
@jsmnbom Seems equally janky, if not more so, but it's really cool ^^ |
Bibo-Joshi commentedOct 16, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Your approach looks good,@jsmnbom, but it only seems to work for bot methods that get the
and
within Or am I missing something? |
@Bibo-Joshi We could still save the |
Simply storing |
@Bibo-Joshi In my mind, there are two different problems here:
Your PR already handles the second problem pretty well, IMO, with the help of the Is there a third case or am i missing some other problem with this? |
Yea in my opinion the best way to do it is using the snippet i posted, but then keeping a lot of your code for the InlineQuery stuff ^^ |
Okidok, then we're all on the same page :) Just wanted to clarify, before starting to work on it ;) |
Bibo-Joshi commentedOct 16, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
mh … I implemented the changes@jsmnbom suggested for the default parameters, but now I'm having trouble adjusting the tests. Since I can't just alter
in the routines (and reset to 'None' afterwards). However that causes (at least i thinks that's the connection) other tests to fail. E.g. after Do you have any hint on how to handle this,@jh0ker@jsmnbom ? Update:
instead of above snipped and that seems to work 💃 |
Uh oh!
There was an error while loading.Please reload this page.
|
Well, a |
Bibo-Joshi commentedJan 20, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Latest commits add Regarding failed tests:
|
This reverts commit1baa91a.
* Rename Test suite* Actually change the badge in readme* fix download without path arguments (#1591)* fix download without path arguments* fix download without path arguments* solved downloading a file without file_path or custom_path* if no file_path, download as file_id* Add test case* Elaborate doc stringCo-authored-by: Bibo-Joshi <hinrich.mahler@freenet.de>* Add default values (#1490)* added parse_mode parameter in Updater and in Bot class to set a default parse mode for bot* DefaultValue* Add default parse_mode everywhere* Renome to default_parse_mode* Test def parse_mode for send_*, edit_message_** Remove duplicate code in Input* classes* Improve handling of def_p_m for Bot methods* Remove unneeded deletion of kwargs* Make@log preserve signature, add bots with defaults to tests* Fix Codacy* Fix Travis Error* Add default_disable_notification* Add default_disable_web_page_preview* Add default_disable_timeout* add default_disable_web_page_preview for InputTextMessageContent* add default_quote* Try fixing test_pin_and_unpin* Just run 3.5 tests for paranoia* add tests for Defaults* Revert "Just run 3.5 tests for paranoia"This reverts commit1baa91a.* Tidy up parameters, move Defaults to ext* Stage new files, because im an idiot* remove debug prints* change equality checks for DEFAULT_NONE* Some last changes* fix S&R error so that tests actually runCo-authored-by: Ak4zh <agwl.akash@gmail.com>Co-authored-by: Eldinnie <Eldinnie@users.noreply.github.com>* Skip test relying on ordered dicts for 3.5 (#1752)* Rename Test suite* Actually change the badge in readmeCo-authored-by: Gabriel Simonetto <42247511+GabrielSimonetto@users.noreply.github.com>Co-authored-by: Ak4zh <agwl.akash@gmail.com>Co-authored-by: Eldinnie <Eldinnie@users.noreply.github.com>
Uh oh!
There was an error while loading.Please reload this page.
Supersedes/Closes#1226 andcloses#1527
To meet the requirements stated by@Eldinnie in#1226, I added a new class
DefaultValue
to thehelpers
module. It's purpose is to allow to differentiate check if a value is just the default or was set specifically:With
def f(arg=None)
we don't know, ifarg is None
results fromf()
or fromf(None)
.With
def f(arg=DefaultValue(None)
, we can handle those differently.This makes it necessary to add some stuff to the
InlineQueryResult*
forbot.answer_inline_query
to parse the newdefault_parse_mode
correctly. But it does the job :) MaybeDefaultValue
also comes in handy with a future use case …How do the @python-telegram-bot/maintainers feel about this?
For the tests, I tried and added them for the
send_*
andedit_message_*
methods. I'm still not too familiar withpytest
, so please tell if those can be improved.However, I couldn't find a clever way to test the
default_parse_mode
foranswer_inline_query
since I'd somehow have to get hold of the resulting message. Any idea is appreciated :)