Description
When an option is declared with count=True, Typer parses it as a no-value counting flag, but the generated help still displays it as an INTEGER option.
This makes the help text suggest that the user should pass an integer value such as --verbose 3, while the parser actually rejects that form.
Minimal reproducible example
import typer
from typer.testing import CliRunner
app = typer.Typer()
@app.command()
def main(verbose: int = typer.Option(0, count=True)):
print(f"verbose={verbose!r}:{type(verbose).__name__}")
runner = CliRunner()
for args in [
["--help"],
["--verbose"],
["--verbose", "--verbose"],
["--verbose", "3"],
]:
result = runner.invoke(app, args)
print("ARGS:", args)
print("EXIT:", result.exit_code)
print(result.output)
Actual behavior
--verbose is parsed as a counting flag:
ARGS: ['--verbose']
EXIT: 0
verbose=1:int
ARGS: ['--verbose', '--verbose']
EXIT: 0
verbose=2:int
But help shows it as an integer-valued option:
--verbose INTEGER [default: 0]
And the form implied by the help fails:
ARGS: ['--verbose', '3']
EXIT: 2
Got unexpected extra argument (3)
Expected behavior
For count=True, the help output should not display INTEGER, because the option is consumed as a no-value counting flag.
For comparison, Click's native count=True help displays the option as a flag:
import click
@click.command()
@click.option("--verbose", "-v", count=True)
def cli(verbose):
click.echo(verbose)
Options:
-v, --verbose
--help Show this message and exit.
Why this matters
This is a contract mismatch between:
- the option declaration:
typer.Option(..., count=True);
- the parser behavior:
count=True is consumed as a no-value counting flag;
- the help/feedback layer: it is displayed as an
INTEGER option.
Users can be misled by the help into passing --verbose 3, which is rejected at runtime.
Version / source checked
I reproduced this against the current master branch locally.
Relevant code paths appear to be:
typer/main.py: the parameter is passed through as count=parameter_info.count when constructing TyperOption.
typer/core.py: TyperOption.add_to_parser() uses action="count" when self.count is true.
Possible fix direction
Treat count=True as a flag-like option for help/metavar rendering, so the generated help does not show INTEGER for a no-value counting flag.
A regression test could assert that:
typer.Option(0, count=True) help does not show INTEGER;
--verbose --verbose returns 2;
--verbose 3 remains rejected, since count options do not consume an explicit value;
- explicitly declared short flags such as
typer.Option(0, "--verbose", "-v", count=True) still support -vvv.
Submitted with PilotDeck (OpenBMB/PilotDeck).
Description
When an option is declared with
count=True, Typer parses it as a no-value counting flag, but the generated help still displays it as anINTEGERoption.This makes the help text suggest that the user should pass an integer value such as
--verbose 3, while the parser actually rejects that form.Minimal reproducible example
Actual behavior
--verboseis parsed as a counting flag:But help shows it as an integer-valued option:
And the form implied by the help fails:
Expected behavior
For
count=True, the help output should not displayINTEGER, because the option is consumed as a no-value counting flag.For comparison, Click's native
count=Truehelp displays the option as a flag:Why this matters
This is a contract mismatch between:
typer.Option(..., count=True);count=Trueis consumed as a no-value counting flag;INTEGERoption.Users can be misled by the help into passing
--verbose 3, which is rejected at runtime.Version / source checked
I reproduced this against the current
masterbranch locally.Relevant code paths appear to be:
typer/main.py: the parameter is passed through ascount=parameter_info.countwhen constructingTyperOption.typer/core.py:TyperOption.add_to_parser()usesaction="count"whenself.countis true.Possible fix direction
Treat
count=Trueas a flag-like option for help/metavar rendering, so the generated help does not showINTEGERfor a no-value counting flag.A regression test could assert that:
typer.Option(0, count=True)help does not showINTEGER;--verbose --verbosereturns2;--verbose 3remains rejected, since count options do not consume an explicit value;typer.Option(0, "--verbose", "-v", count=True)still support-vvv.Submitted with PilotDeck (OpenBMB/PilotDeck).