pallets / click

Python composable command line interface toolkit
https://click.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
15.64k stars 1.4k forks source link

`show_choices=False` seems to have no effect #2356

Open zmoon opened 2 years ago

zmoon commented 2 years ago

I noticed when using Typer that even if you pass show_choices=False, the choices still get shown in the help. It seems that this is related to Click.

Example:

import click

@click.command()
@click.option('-s', '--string-to-echo', type=click.Choice(['hello', 'world']), show_choices=False)
def echo(string):
    click.echo(string)

if __name__ == "__main__":
    echo()
Usage: ... [OPTIONS]

Options:
  -s, --string-to-echo [hello|world]
  --help                          Show this message and exit.

I guess it isn't documented what show_choices does for Option (if anything) in the non-prompt case, but I expected show_choices=False to disable showing the choices in the help.

Environment:

nachovizzo commented 2 years ago

I have the same problem

nachovizzo commented 2 years ago

It's somehow strange that there is even a test for this case, but for some reason looks not to be failing

https://github.com/pallets/click/blob/fb4327216543d751e2654a0d3bf6ce3d31c435cc/tests/test_termui.py#L198

mrmups commented 2 years ago

It looks like the show_choices option is intended to suppress choices from being displayed inline when click.prompt() is used. It's available to click.option() because an option can act like a prompt if the prompt=True is used.

Adding prompt=True to the option in the original example and running it with no options will result in:

mups@docker:~$ demoecho
String to echo:

Where as setting show_choices=True would result in:

mups@docker:~$ demoecho
String to echo (hello, world):

The help text is showing the metavar of a Choice object. The Choice.get_metavar() method could be updated to to check for the show_choices param and either return None or an empty string.

The None option would cause the param type to be shown, which would look something like this:

mups@docker:~$ demoecho --help         
Usage: demoecho [OPTIONS]

Options:
  -s, --string-to-echo CHOICE  The string echoed back to stdout.
  --help                       Show this message and exit.

But I think the better option in this case would be to return an empty string which would look like this:

mups@docker:~$ demoecho --help         
Usage: demoecho [OPTIONS]

Options:
  -s, --string-to-echo   The string echoed back to stdout.
  --help                 Show this message and exit.

Which do you prefer?

zmoon commented 2 years ago

Hi @mrmups . I think better would be -s, --string-to-echo TEXT or somesuch would be better actually. -s, --string-to-echo by itself kind of suggests boolean flag.

mrmups commented 2 years ago

@zmoon Good point. In fact, it should probably just create a set of metavars based on the ParamType of each choice value. This would result in this for the original example:

mups@docker:~$ demoecho --help         
Usage: demoecho [OPTIONS]

Options:
  -s, --string [TEXT]  This value echoed back to stdout.
  --help                       Show this message and exit.

and if we added the choice 123:

mups@docker:~$ demoecho --help         
Usage: demoecho [OPTIONS]

Options:
  -s, --string [TEXT|INTEGER]  This value echoed back to stdout.
  --help                       Show this message and exit.