I'm having an issue accessing the default values for the other input arguments from Python's click module (Version 6.7 running on Python 3.6) during a callback on a particular parameter. The goal of my callback would be to parse a set of numbers based on all of the other inputs and return that as the input argument to the function. However, depending on how things are called from the command line, the click context is unable access the default arguments or even some of the command line inputs depending on the order in which they are used. Now, a solution to this problem may be to handle this parsing within the function, but I feel that it should be possible to do this in the callback, so I'd like to try and make it work if possible.
Consider the following minimal example:
import click
def check_number(ctx, _, input_):
"""Do some calculations to check the number"""
p = ctx.params
# Print defaults as I see them here.
print('User:', p.get('user', None))
print('Start Date:', p.get('start_date', None))
print('End Date:', p.get('end_date', None))
print('Number:', input_)
# Number is typically a range of numbers that needs to be parsed.
# Here I would revise the input and return whats left after my check
return input_
@click.command()
@click.option('--user','user', default='Default User')
@click.option('--start','start_date', default='2000_0101')
@click.option('--end','end_date',default='2020_0101')
@click.option('--number','number', default=0, callback=check_number)
def main(user, start_date, end_date, number):
"""Do some stuff."""
if __name__ == '__main__':
main()
Running the script without invoking any options retrieves the defaults as expected.
> ./click_context_problem.py
User: Default User
Start Date: 2000_0101
End Date: 2020_0101
Number: 0
However, if I start to add input arguments, it becomes unable to recover the default values. For instance:
> ./click_context_problem.py --number=1
User: None
Start Date: None
End Date: None
Number: 1
Now, it is able to see some inputs if I add them to the command line, but only if it is before the --number
option, as seen below:
> ./click_context_problem.py --user=me --number=1
User: me
Start Date: None
End Date: None
Number: 1
> ./click_context_problem.py --number=1 --user=me
User: None
Start Date: None
End Date: None
Number: 1
I had seen a proposed solution somewhere (which I can't find anymore unfortunately) that proposed making a click.Command
subclass that looks like the following:
class GatherOptions(click.Command):
"""This class makes sure all of the input arguments are gathered and passed through the context for the option callbacks."""
def make_context(self, *args, **kwargs):
ctx = super(GatherOptions, self).make_context(*args, *kwargs)
return ctx
...
@click.command(cls=GatherOptions) # Add this class here
However, I don't really see what this does as the call to the super class doesn't seem altered in any way. But perhaps the make_context
method can be invoked in some other way in order to access the defaults. In any case, it doesn't change the behavior of my program whether thats there or not.