typer icon indicating copy to clipboard operation
typer copied to clipboard

Prompt only if `--option`'s `argument` isn't provided

Open yozachar opened this issue 1 year ago • 3 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the Typer documentation, with the integrated search.
  • [X] I already searched in Google "How to X in Typer" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to Typer but to Click.

Commit to Help

After submitting this, I commit to one of:

  • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
  • I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
  • Implement a Pull Request for a confirmed bug.
  • [X] I commit to help with one of those options 👆

Example Code

import typer


cli = typer.Typer()


@cli.command()
def req(
    username: str = 'admin',
    password: str = typer.Option(
        'default',
        prompt=typer.prompt('Password'), # True,
        # prompt_required=True,
    )
) -> None:
    print(f'Username: {username} | Password: {password}')

cli()

Description

  • Assume that the above code runs directly with command req

  • ~~I would prefer if it were possible to provide password via prompt and not on commandline~~

  • ~~Additionlly, using getpass & getuser seems more favourable.~~

  • When I provide a command like:

    $ req --username myuser --password
    

    It prompts, but afterword it runs into error:

    Password:
    Error: Option '--password,' requires an argument
    

Wanted Solution

Prompt for (here) password only when --password is passed w/o any argument.

Wanted Code

# NAY

Alternatives

NA

Operating System

Linux

Operating System Details

Arch Linux Kernel: 5.18

Typer Version

0.6.1

Python Version

3.10.5

Additional Context

No response

yozachar avatar Jul 19 '22 01:07 yozachar

My bad, I do not understand this behavior:

~/test via 🐍 v3.10.5 (test)
➜ python -m test_typer --password "def"
Password: abc # why prompt at all?
Username: admin | Password: def

~/test via 🐍 v3.10.5 (test)
➜ python -m test_typer
Password: def
def [default]: 123 # why? what's this?!
Username: admin | Password: 123

~/test via 🐍 v3.10.5 (test) 
➜ python -m test_typer --password      
Password: 123 # why not read from here?
Error: Option '--password' requires an argument

Can someone please explain?

yozachar avatar Jul 19 '22 02:07 yozachar

I think something like this could give you what you want to achieve, if I've understood correctly. Instead of specifying the --password option and leaving it blank, you just don't use that option at all.

import typer


def main(
    user: str,
    password: str = typer.Option("", help="Enter your password."),
):
    if password:
        print(f"{user} and {password}")
    else:
        new_password = typer.prompt("Enter your password", confirmation_prompt=True, hide_input=True)
        print(f"user is: {user} and password is: {new_password}")


if __name__ == "__main__":
    typer.run(main)

As far as I can tell, if you add an option, then use the option when you are running the program on the command line, you have to specify some value for that option - i.e. there is no way to leave it blank. So I don't think the way you're trying to solve this is possible.

osintalex avatar Aug 02 '22 03:08 osintalex

Yup, I've done something like this.

... if you add an option, then use the option when you are running the program on the command line, you have to specify some value for that option ...

Right, but it feels counter intuitive when used with prompt

yozachar avatar Aug 04 '22 09:08 yozachar

prompt actually takes in a boolean so i believe that what you actually want it:

import typer

cli = typer.Typer()


@cli.command()
def req(
    username: str = "admin",
    password: str = typer.Option("default", prompt=True),
) -> None:
    print(f"Username: {username} | Password: {password}")

cli()

Output:

$ python /tmp/asd/potato/potato/main.py
Password [default]: hello
Username: admin | Password: hello

heiskane avatar Sep 21 '23 18:09 heiskane

Thanks @heiskane!

yozachar avatar Sep 22 '23 09:09 yozachar