diff --git a/docs_src/arguments/help/tutorial006_an_py310.py b/docs_src/arguments/help/tutorial006_an_py310.py index bcdd0d17a0..ebef3e93e6 100644 --- a/docs_src/arguments/help/tutorial006_an_py310.py +++ b/docs_src/arguments/help/tutorial006_an_py310.py @@ -6,7 +6,7 @@ @app.command() -def main(name: Annotated[str, typer.Argument(metavar="✨username✨")] = "World"): +def main(name: Annotated[str, typer.Argument(metavar="✨user✨")] = "World"): print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial006_py310.py b/docs_src/arguments/help/tutorial006_py310.py index 1aa65971e7..edd1f7ddb1 100644 --- a/docs_src/arguments/help/tutorial006_py310.py +++ b/docs_src/arguments/help/tutorial006_py310.py @@ -4,7 +4,7 @@ @app.command() -def main(name: str = typer.Argument("World", metavar="✨username✨")): +def main(name: str = typer.Argument("World", metavar="✨user✨")): print(f"Hello {name}") diff --git a/tests/test_rich_utils.py b/tests/test_rich_utils.py index f16a3564a7..3f21e49ba6 100644 --- a/tests/test_rich_utils.py +++ b/tests/test_rich_utils.py @@ -76,7 +76,7 @@ def main( result = runner.invoke(app, ["--help"]) assert "Usage" in result.stdout - assert "name" in result.stdout + assert "NAME" in result.stdout assert "option-1" in result.stdout assert "option-2" in result.stdout assert result.stdout.count("[default: None]") == 0 @@ -108,31 +108,31 @@ def main(bar: str): @pytest.mark.parametrize("input_text", ["[ARGS]", "[ARGS]..."]) def test_metavar_highlighter(input_text: str): """ - Test that the MetavarHighlighter works correctly. + Test that the TypesHighlighter (used to be the MetavarHighlighter) works correctly. cf PR 1508 """ from typer.rich_utils import ( - STYLE_METAVAR_SEPARATOR, + STYLE_TYPES_SEPARATOR, Text, _get_rich_console, - metavar_highlighter, + types_highlighter, ) console = _get_rich_console() text = Text(input_text) - highlighted = metavar_highlighter(text) + highlighted = types_highlighter(text) console.print(highlighted) # Get the style for each bracket opening_bracket_style = highlighted.get_style_at_offset(console, 0) closing_bracket_style = highlighted.get_style_at_offset(console, 5) - # The opening bracket should have metavar_sep style - assert str(opening_bracket_style) == STYLE_METAVAR_SEPARATOR + # The opening bracket should have types_sep style + assert str(opening_bracket_style) == STYLE_TYPES_SEPARATOR - # The closing bracket should have metavar_sep style (fails before PR 1508 when there are 3 dots) - assert str(closing_bracket_style) == STYLE_METAVAR_SEPARATOR + # The closing bracket should have types_sep style (fails before PR 1508 when there are 3 dots) + assert str(closing_bracket_style) == STYLE_TYPES_SEPARATOR def test_make_rich_text_with_ansi_escape_sequences(): @@ -222,3 +222,43 @@ def find_right_boundary_pos(line): assert pos_a == pos_b == pos_c, ( f"Right boundaries not aligned: A={pos_a}, B={pos_b}, C={pos_c}" ) + + +def test_rich_help_metavar(): + app = typer.Typer(rich_markup_mode="rich") + + @app.command() + def main( + *, + 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="meta7"), + arg8: int = typer.Argument(metavar="ARG8"), + arg9: int = typer.Argument(metavar="arg9"), + ): + pass # pragma: no cover + + result = runner.invoke(app, ["--help"]) + assert "Usage: main [OPTIONS] ARG1 ARG3 [ARG4] [meta7] ARG8 arg9" in result.stdout + + out_nospace = result.stdout.replace(" ", "") + + # arguments + assert "ARG1INTEGER" in out_nospace + assert "ARG3INTEGER" in out_nospace + assert "[ARG4]INTEGER" in out_nospace + assert "[meta7]INTEGER" in out_nospace + assert "ARG8INTEGER" in out_nospace + assert "arg9INTEGER" in out_nospace + + assert "arg7" not in result.stdout.lower() + assert "ARG9" not in result.stdout + + # options + assert "arg2INTEGER" in out_nospace + assert "arg5INTEGER" in out_nospace + assert "arg6INTEGER" in out_nospace diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py index 5e563b713d..c0f359fb85 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial006.py @@ -4,6 +4,7 @@ from types import ModuleType import pytest +import typer from typer.testing import CliRunner runner = CliRunner() @@ -22,16 +23,31 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: return mod -def test_help(mod: ModuleType): - result = runner.invoke(mod.app, ["--help"]) +@pytest.fixture( + name="app", + params=[ + pytest.param(None), + pytest.param("rich"), + ], +) +def get_app(mod: ModuleType, request: pytest.FixtureRequest) -> typer.Typer: + rich_markup_mode = request.param + app = typer.Typer(rich_markup_mode=rich_markup_mode) + app.command()(mod.main) + return app + + +def test_help(app): + result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 - assert "Usage: main [OPTIONS] [✨username✨]" in result.output + assert "Usage: main [OPTIONS] [✨user✨]" in result.output assert "Arguments" in result.output + assert "name" not in result.output assert "[default: World]" in result.output -def test_call_arg(mod: ModuleType): - result = runner.invoke(mod.app, ["Camila"]) +def test_call_arg(app): + result = runner.invoke(app, ["Camila"]) assert result.exit_code == 0 assert "Hello Camila" in result.output diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial007.py b/tests/test_tutorial/test_commands/test_help/test_tutorial007.py index 5cc81eae20..5978f60980 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial007.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial007.py @@ -36,10 +36,10 @@ def test_main_help(mod: ModuleType): def test_create_help(mod: ModuleType): result = runner.invoke(mod.app, ["create", "--help"]) assert result.exit_code == 0 - assert "username" in result.output + assert "USERNAME" in result.output assert "The username to create" in result.output assert "Secondary Arguments" in result.output - assert "lastname" in result.output + assert "LASTNAME" in result.output assert "The last name of the new user" in result.output assert "--force" in result.output assert "--no-force" in result.output diff --git a/typer/rich_utils.py b/typer/rich_utils.py index d85043238c..0a6d36bebb 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -30,8 +30,8 @@ STYLE_SWITCH = "bold green" STYLE_NEGATIVE_OPTION = "bold magenta" STYLE_NEGATIVE_SWITCH = "bold red" -STYLE_METAVAR = "bold yellow" -STYLE_METAVAR_SEPARATOR = "dim" +STYLE_TYPES = "bold yellow" +STYLE_TYPES_SEPARATOR = "dim" STYLE_USAGE = "yellow" STYLE_USAGE_COMMAND = "bold" STYLE_DEPRECATED = "red" @@ -109,7 +109,7 @@ class OptionHighlighter(RegexHighlighter): highlights = [ r"(^|\W)(?P\-\w+)(?![a-zA-Z0-9])", r"(^|\W)(?P