diff --git a/tests/test_core.py b/tests/test_core.py index 2cb759918b..9f24efa5c8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -377,3 +377,30 @@ def main(names: list[str] = typer.Option(None)): result = runner.invoke(app, [], default_map={"names": "not-a-list"}) assert result.exit_code == 2 assert "Invalid value" in result.output + + +def test_count_option_help_no_metavar() -> None: + """Regression test for https://github.com/fastapi/typer/issues/1869. + + count=True options should not show INTEGER in help since they don't take a value. + """ + app = typer.Typer() + + @app.command() + def main(verbose: int = typer.Option(0, count=True)): + """Count verbosity.""" + typer.echo(f"verbose={verbose}") + + result = runner.invoke(app, ["--help"]) + assert result.exit_code == 0 + # The help must not show INTEGER for a count option + assert "INTEGER" not in result.output + assert "--verbose" in result.output + + # Behaviour: --verbose increments + assert runner.invoke(app, ["--verbose"]).exit_code == 0 + + # Behaviour: --verbose 3 is rejected (count doesn't accept a value) + result = runner.invoke(app, ["--verbose", "3"]) + assert result.exit_code == 2 + assert "unexpected extra argument" in result.output diff --git a/typer/core.py b/typer/core.py index 6868ab4355..a6c414b20e 100644 --- a/typer/core.py +++ b/typer/core.py @@ -743,6 +743,8 @@ def _extract_default_help_str( return _extract_default_help_str(self, ctx=ctx) def make_metavar(self, ctx: _click.Context) -> str: + if self.count: + return "" return super().make_metavar(ctx=ctx) def get_help_record(self, ctx: _click.Context) -> tuple[str, str] | None: diff --git a/typer/rich_utils.py b/typer/rich_utils.py index de68f60644..2202f98bb4 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -397,9 +397,10 @@ def _print_options_panel( types_data = Text(style=STYLE_TYPES, overflow="fold") # Fetch type + is_count_option: bool = isinstance(param, TyperOption) and param.count if metavar_type and metavar_type != "BOOLEAN": types_data.append(metavar_type) - else: + elif not is_count_option: type_str = param.type.name.upper() if type_str != "BOOLEAN": types_data.append(type_str)