typer
typer copied to clipboard
Bad argument help for type of optional argument
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
- [x] I commit to help with one of those options 👆
Example Code
import typer
from typing import Optional
def main(name: Optional[str] = typer.Argument(None)):
if name:
typer.echo(f'Name: {name}')
if __name__ == '__main__':
typer.run(main)
Description
For optional arguments Typer shows their metavar instead of type in argument help. For above example instead of TEXT
we get [NAME]
in argument help.
Operating System
macOS
Operating System Details
No response
Typer Version
0.6.1
Python Version
3.10
Additional Context
No response
You can manually specify the metavar like this:
import typer
from typing import Optional
def main(name: Optional[str] = typer.Argument(None, metavar='name')):
if name:
typer.echo(f'Name: {name}')
if __name__ == '__main__':
typer.run(main)
Yes, but this is erasing the problem.
I would say that issue is caused by logic in here: https://github.com/tiangolo/typer/blob/7f44e6db6267efa87918e8700212de41a7fbdc3e/typer/rich_utils.py#L367-L377
To reiterate the exact issue - following code:
import sys, typer
sys.argv[1:] = ['--help']
def example(*,
arg1: int,
arg2: int = 42,
arg3: int = typer.Argument(...),
arg4: int = typer.Argument(42),
arg5: int = typer.Option(...),
arg6: int = typer.Option(42),
arg7: int = typer.Argument(42, metavar='metaarg7'),
arg8: int = typer.Argument(42, metavar='ARG8'),
):
pass
typer.run(example)
Produces following help message:
Usage: Example.py [OPTIONS] ARG1 ARG3 [ARG4] metaarg7 ARG8
Arguments:
* arg1 INTEGER [default: None] [required]
* arg3 INTEGER [default: None] [required]
arg4 [ARG4] [default: 42]
arg7 metaarg7 [default: 42]
arg8 INTEGER [default: 42]
Options:
--arg2 INTEGER [default: 42]
* --arg5 INTEGER [default: None] [required]
--arg6 INTEGER [default: 42]
The usage example works as intended and documented - for each argument a metavar is displayed.
The issue is in rest of help message. As the code is written - the second column is designed to contain metavar. But due to condition metavar_str == param.name.upper()
in most cases it actually contains type name instead of metavar. It is also containing type for all options.
While this condition is core of the issue it probably was added quite reasonably - because metavar column is not really useful. Similarly to OP, I would also prefer changing this column to just always contain type.