From b0538d8022171c2548a9b3155b3a8ca16e3754d5 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 11:00:38 +0200 Subject: [PATCH 01/29] updated tests for more consistent & clean metavar printing --- tests/assets/cli/multiapp-docs-title.md | 8 +-- tests/assets/cli/multiapp-docs.md | 8 +-- tests/assets/cli/richformattedapp-docs.md | 6 +- tests/test_cli/test_help.py | 2 +- tests/test_core.py | 60 +++++++++++++++++++ tests/test_prog_name.py | 2 +- tests/test_rich_markup_mode.py | 2 +- tests/test_rich_utils.py | 29 +++++---- .../test_default/test_tutorial001.py | 2 +- .../test_default/test_tutorial002.py | 2 +- .../test_envvar/test_tutorial001.py | 4 +- .../test_envvar/test_tutorial002.py | 2 +- .../test_envvar/test_tutorial003.py | 2 +- .../test_help/test_tutorial001.py | 8 +-- .../test_help/test_tutorial002.py | 4 +- .../test_help/test_tutorial003.py | 4 +- .../test_help/test_tutorial004.py | 4 +- .../test_help/test_tutorial005.py | 2 +- .../test_help/test_tutorial008.py | 4 +- .../test_optional/test_tutorial000.py | 2 +- .../test_optional/test_tutorial001.py | 4 +- .../test_optional/test_tutorial002.py | 2 +- .../test_optional/test_tutorial003.py | 4 +- .../test_arguments/test_tutorial001.py | 4 +- .../test_help/test_tutorial001.py | 4 +- .../test_help/test_tutorial007.py | 2 +- .../test_first_steps/test_tutorial002.py | 2 +- .../test_first_steps/test_tutorial003.py | 2 +- .../test_first_steps/test_tutorial004.py | 4 +- .../test_first_steps/test_tutorial005.py | 4 +- .../test_tutorial002.py | 2 +- .../test_help/test_tutorial003.py | 2 +- .../test_help/test_tutorial004.py | 2 +- .../test_name/test_tutorial001.py | 2 +- .../test_name/test_tutorial002.py | 2 +- .../test_name/test_tutorial003.py | 2 +- .../test_name/test_tutorial004.py | 2 +- .../test_name/test_tutorial005.py | 2 +- .../test_password/test_tutorial001.py | 2 +- .../test_password/test_tutorial002.py | 2 +- .../test_prompt/test_tutorial001.py | 2 +- .../test_prompt/test_tutorial002.py | 2 +- .../test_prompt/test_tutorial003.py | 2 +- .../test_tutorial001_tutorial002.py | 4 +- .../test_datetime/test_tutorial001.py | 2 +- .../test_enum/test_tutorial001.py | 2 +- .../test_enum/test_tutorial003.py | 2 +- .../test_enum/test_tutorial004.py | 2 +- .../test_index/test_tutorial001.py | 4 +- .../test_number/test_tutorial001.py | 8 +-- .../test_typer_app/test_tutorial001.py | 2 +- tests/test_types.py | 4 +- 52 files changed, 154 insertions(+), 91 deletions(-) diff --git a/tests/assets/cli/multiapp-docs-title.md b/tests/assets/cli/multiapp-docs-title.md index ffde843736..368275838f 100644 --- a/tests/assets/cli/multiapp-docs-title.md +++ b/tests/assets/cli/multiapp-docs-title.md @@ -65,8 +65,8 @@ $ multiapp sub hello [OPTIONS] **Options**: -* `--name TEXT`: [default: World] -* `--age INTEGER`: The age of the user [default: 0] +* `--name `: [default: World] +* `--age `: The age of the user [default: 0] * `--help`: Show this message and exit. ### `multiapp sub hi` @@ -76,12 +76,12 @@ Say Hi **Usage**: ```console -$ multiapp sub hi [OPTIONS] [USER] +$ multiapp sub hi [OPTIONS] [user] ``` **Arguments**: -* `[USER]`: The name of the user to greet [default: World] +* `[user]`: The name of the user to greet [default: World] **Options**: diff --git a/tests/assets/cli/multiapp-docs.md b/tests/assets/cli/multiapp-docs.md index 67d02568db..e1dad5f804 100644 --- a/tests/assets/cli/multiapp-docs.md +++ b/tests/assets/cli/multiapp-docs.md @@ -65,8 +65,8 @@ $ multiapp sub hello [OPTIONS] **Options**: -* `--name TEXT`: [default: World] -* `--age INTEGER`: The age of the user [default: 0] +* `--name `: [default: World] +* `--age `: The age of the user [default: 0] * `--help`: Show this message and exit. ### `multiapp sub hi` @@ -76,12 +76,12 @@ Say Hi **Usage**: ```console -$ multiapp sub hi [OPTIONS] [USER] +$ multiapp sub hi [OPTIONS] [user] ``` **Arguments**: -* `[USER]`: The name of the user to greet [default: World] +* `[user]`: The name of the user to greet [default: World] **Options**: diff --git a/tests/assets/cli/richformattedapp-docs.md b/tests/assets/cli/richformattedapp-docs.md index 678a2daf6f..a6d1ab1dc3 100644 --- a/tests/assets/cli/richformattedapp-docs.md +++ b/tests/assets/cli/richformattedapp-docs.md @@ -5,13 +5,13 @@ Say cool name of the user [required] -* `[USER_2]`: The world [default: The World] +* `user_1`: The cool name of the user [required] +* `[user_2]`: The world [default: The World] **Options**: diff --git a/tests/test_cli/test_help.py b/tests/test_cli/test_help.py index e829c5801b..3238c0658b 100644 --- a/tests/test_cli/test_help.py +++ b/tests/test_cli/test_help.py @@ -121,7 +121,7 @@ def cmd(value: str) -> None: output_lines = result.output.splitlines() usage_idx = output_lines.index("Usage: very-long-program-name-that-forces-wrap ") args_line = output_lines[usage_idx + 1] - assert args_line.lstrip() == "[OPTIONS] VALUE" + assert args_line.lstrip() == "[OPTIONS] {value}" assert args_line.startswith(" ") diff --git a/tests/test_core.py b/tests/test_core.py index 2cb759918b..c3920ab883 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -377,3 +377,63 @@ 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_parameter_name_casing(): + app = typer.Typer() + + @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.Option(metavar="ARG9"), + ): + print( + f"arg1={arg1} arg2={arg2} arg3={arg3} ARG4={ARG4} ARG5={ARG5} " + f"arg6={arg6} arg7={arg7} arg8={arg8} arg9={arg9}" + ) + + result = runner.invoke( + app, + [ + "1", + "3", + "4", + "7", + "8", + "--arg2", + "2", + "--ARG5", + "5", + "--arg6", + "6", + "--ARG9", + "9", + ], + ) + assert result.exit_code == 0 + assert ( + "arg1=1 arg2=2 arg3=3 ARG4=4 ARG5=5 arg6=6 arg7=7 arg8=8 arg9=9" + in result.output + ) + + result = runner.invoke(app, ["1", "3", "4", "7", "8", "--ARG5", "5", "--ARG9", "9"]) + assert result.exit_code == 0 + assert ( + "arg1=1 arg2=42 arg3=3 ARG4=4 ARG5=5 arg6=42 arg7=7 arg8=8 arg9=9" + in result.output + ) + + result = runner.invoke(app, ["1", "3", "4", "7", "8", "--arg5", "5", "--ARG9", "9"]) + assert result.exit_code != 0 + assert "No such option: --arg5" in result.output + + result = runner.invoke(app, ["1", "3", "4", "7", "8", "--ARG5", "5", "--arg9", "9"]) + assert result.exit_code != 0 + assert "No such option: --arg9" in result.output diff --git a/tests/test_prog_name.py b/tests/test_prog_name.py index cfb5a3464f..5de6fd3f7a 100644 --- a/tests/test_prog_name.py +++ b/tests/test_prog_name.py @@ -10,4 +10,4 @@ def test_custom_prog_name(): capture_output=True, encoding="utf-8", ) - assert "Usage: custom-name [OPTIONS] I" in result.stdout + assert "Usage: custom-name [OPTIONS] {i}" in result.stdout diff --git a/tests/test_rich_markup_mode.py b/tests/test_rich_markup_mode.py index abfae82790..94fb4c2ae8 100644 --- a/tests/test_rich_markup_mode.py +++ b/tests/test_rich_markup_mode.py @@ -25,7 +25,7 @@ def main(arg: str): assert "Hello World" in result.stdout result = runner.invoke(app, ["--help"]) - assert "ARG [required]" in result.stdout + assert "arg [required]" in result.stdout assert all(c not in result.stdout for c in rounded) diff --git a/tests/test_rich_utils.py b/tests/test_rich_utils.py index beb914b961..6d11652d77 100644 --- a/tests/test_rich_utils.py +++ b/tests/test_rich_utils.py @@ -101,7 +101,7 @@ def main(bar: str): result = runner.invoke(app, ["--help"]) assert "Usage" in result.stdout - assert "BAR" in result.stdout + assert "{bar}" in result.stdout @needs_rich @@ -233,8 +233,8 @@ def main( arg1: int, arg2: int = 42, arg3: int = typer.Argument(...), - arg4: int = typer.Argument(42), - arg5: int = typer.Option(...), + 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"), @@ -243,23 +243,26 @@ def main( pass # pragma: no cover result = runner.invoke(app, ["--help"]) - assert "Usage: main [OPTIONS] ARG1 ARG3 [ARG4] [meta7] ARG8 arg9" in result.stdout + 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 "arg1" in out_nospace + assert "arg3" in out_nospace + assert "[ARG4]" in out_nospace + assert "[meta7]" in out_nospace + assert "ARG8" in out_nospace + assert "arg9" in out_nospace assert "arg7" not in result.stdout.lower() assert "arg8" not in result.stdout assert "ARG9" not in result.stdout # options - assert "arg2INTEGER" in out_nospace - assert "arg5INTEGER" in out_nospace - assert "arg6INTEGER" in out_nospace + assert "--arg2" in out_nospace + assert "--ARG5" in out_nospace + assert "--arg6" in out_nospace diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py index 75104a7d9b..81212ce98b 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial001.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "[default: Wade Wilson]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py index f68b61df82..37eedd779d 100644 --- a/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_default/test_tutorial002.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "[default: (dynamic)]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py index 689030a258..179f6936fc 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py @@ -27,7 +27,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "env var: AWESOME_NAME" in result.output assert "default: World" in result.output @@ -37,7 +37,7 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "env var: AWESOME_NAME" in result.output assert "default: World" in result.output diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py index 23679b04b5..3d06a1c869 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial002.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "env var: AWESOME_NAME, GOD_NAME" in result.output assert "default: World" in result.output diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py index ee979e4762..042620f9a0 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial003.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "env var: AWESOME_NAME" not in result.output assert "default: World" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py index fabe28be28..e2e24fe647 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py @@ -26,9 +26,9 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] NAME" in result.output + assert "[OPTIONS] {name}" in result.output assert "Arguments" in result.output - assert "NAME" in result.output + assert "{name}" in result.output assert "The name of the user to greet" in result.output assert "[required]" in result.output @@ -37,9 +37,9 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] NAME" in result.output + assert "[OPTIONS] {name}" in result.output assert "Arguments" in result.output - assert "NAME" in result.output + assert "{name}" in result.output assert "The name of the user to greet" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py index 91eb30e375..f3fd10a9d1 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py @@ -25,10 +25,10 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] NAME" in result.output + assert "[OPTIONS] {name}" in result.output assert "Say hi to NAME very gently, like Dirk." in result.output assert "Arguments" in result.output - assert "NAME" in result.output + assert "{name}" in result.output assert "The name of the user to greet" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py index 20bd6b76ea..dc7ef0234c 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py @@ -25,10 +25,10 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Say hi to NAME very gently, like Dirk." in result.output assert "Arguments" in result.output - assert "NAME" in result.output + assert "[name]" in result.output assert "Who to greet" in result.output assert "[default: World]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py index 7a20f48979..451e3272ad 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py @@ -25,10 +25,10 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Say hi to NAME very gently, like Dirk." in result.output assert "Arguments" in result.output - assert "NAME" in result.output + assert "[name]" in result.output assert "Who to greet" in result.output assert "[default: World]" not in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py index 8f6d356d81..4cb17b4e86 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial005.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "Usage: main [OPTIONS] [NAME]" in result.output + assert "Usage: main [OPTIONS] [name]" in result.output assert "Arguments" in result.output assert "Who to greet" in result.output assert "[default: (Deadpoolio the amazing's name)]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py index f21c883434..004dbbcfe1 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py @@ -26,7 +26,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Say hi to NAME very gently, like Dirk." in result.output assert "Arguments" not in result.output assert "[default: World]" not in result.output @@ -36,7 +36,7 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output assert "Say hi to NAME very gently, like Dirk." in result.output assert "Arguments" not in result.output assert "[default: World]" not in result.output diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial000.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial000.py index 8f0bd34c7f..76d86ed82e 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial000.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial000.py @@ -39,7 +39,7 @@ def test_cli(app: typer.Typer): def test_cli_missing_argument(app: typer.Typer): result = runner.invoke(app) assert result.exit_code == 2 - assert "Missing argument 'NAME'" in result.output + assert "Missing argument 'name'" in result.output def test_script(mod: ModuleType): diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py index 7e26b9eb86..60d4b5d30d 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py @@ -26,7 +26,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_call_no_arg(mod: ModuleType): result = runner.invoke(mod.app) assert result.exit_code != 0 - assert "Missing argument 'NAME'." in result.output + assert "Missing argument 'name'." in result.output def test_call_no_arg_standalone(mod: ModuleType): @@ -40,7 +40,7 @@ def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app) assert result.exit_code != 0 - assert "Error: Missing argument 'NAME'" in result.output + assert "Error: Missing argument 'name'" in result.output def test_call_arg(mod: ModuleType): diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py index 3e3fdba384..b1b1c9b07b 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial002.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAME]" in result.output + assert "[OPTIONS] [name]" in result.output def test_call_no_arg(mod: ModuleType): diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py index 60addad04d..274616e04c 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py @@ -15,7 +15,7 @@ def test_call_no_arg(): result = runner.invoke(app) assert result.exit_code != 0 - assert "Missing argument 'NAME'." in result.output + assert "Missing argument 'name'." in result.output def test_call_no_arg_standalone(): @@ -29,7 +29,7 @@ def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(app) assert result.exit_code != 0 - assert "Error: Missing argument 'NAME'" in result.output + assert "Error: Missing argument 'name'" in result.output def test_call_arg(): diff --git a/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py b/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py index 4efc1fe9ef..58ac250108 100644 --- a/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_arguments/test_tutorial001.py @@ -13,13 +13,13 @@ def test_help_create(): result = runner.invoke(app, ["create", "--help"]) assert result.exit_code == 0 - assert "create [OPTIONS] USERNAME" in result.output + assert "create [OPTIONS] {username}" in result.output def test_help_delete(): result = runner.invoke(app, ["delete", "--help"]) assert result.exit_code == 0 - assert "delete [OPTIONS] USERNAME" in result.output + assert "delete [OPTIONS] {username}" in result.output def test_create(): diff --git a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py index 9993765b37..751022c673 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial001.py @@ -39,14 +39,14 @@ def test_help(mod: ModuleType): def test_help_create(mod: ModuleType): result = runner.invoke(mod.app, ["create", "--help"]) assert result.exit_code == 0 - assert "create [OPTIONS] USERNAME" in result.output + assert "create [OPTIONS] {username}" in result.output assert "Create a new user with USERNAME." in result.output def test_help_delete(mod: ModuleType): result = runner.invoke(mod.app, ["delete", "--help"]) assert result.exit_code == 0 - assert "delete [OPTIONS] USERNAME" in result.output + assert "delete [OPTIONS] {username}" in result.output assert "Delete a user with USERNAME." in result.output assert "--force" in result.output assert "--no-force" 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 76c7cb2a4f..7b8fe367ed 100644 --- a/tests/test_tutorial/test_commands/test_help/test_tutorial007.py +++ b/tests/test_tutorial/test_commands/test_help/test_tutorial007.py @@ -36,7 +36,7 @@ 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 "create [OPTIONS] USERNAME [LASTNAME]" in result.output + assert "create [OPTIONS] {username} [lastname]" in result.output assert "username" in result.output assert "The username to create" in result.output assert "Secondary Arguments" in result.output diff --git a/tests/test_tutorial/test_first_steps/test_tutorial002.py b/tests/test_tutorial/test_first_steps/test_tutorial002.py index 952f983963..baceee2bc2 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial002.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial002.py @@ -15,7 +15,7 @@ def test_1(): result = runner.invoke(app, []) assert result.exit_code != 0 - assert "Missing argument 'NAME'" in result.output + assert "Missing argument 'name'" in result.output def test_2(): diff --git a/tests/test_tutorial/test_first_steps/test_tutorial003.py b/tests/test_tutorial/test_first_steps/test_tutorial003.py index e92f23521e..5c5ddb39cf 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial003.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial003.py @@ -15,7 +15,7 @@ def test_1(): result = runner.invoke(app, ["Camila"]) assert result.exit_code != 0 - assert "Missing argument 'LASTNAME'" in result.output + assert "Missing argument 'lastname'" in result.output def test_2(): diff --git a/tests/test_tutorial/test_first_steps/test_tutorial004.py b/tests/test_tutorial/test_first_steps/test_tutorial004.py index 6ac326f074..0232605f97 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial004.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial004.py @@ -16,9 +16,9 @@ def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "Arguments" in result.output - assert "NAME" in result.output + assert "{name}" in result.output assert "[required]" in result.output - assert "LASTNAME" in result.output + assert "{lastname}" in result.output assert "[required]" in result.output assert "--formal" in result.output assert "--no-formal" in result.output diff --git a/tests/test_tutorial/test_first_steps/test_tutorial005.py b/tests/test_tutorial/test_first_steps/test_tutorial005.py index 87ce389410..48c80573f1 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial005.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial005.py @@ -16,10 +16,10 @@ def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "Arguments" in result.output - assert "NAME" in result.output + assert "{name}" in result.output assert "[required]" in result.output assert "--lastname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "--formal" in result.output assert "--no-formal" in result.output diff --git a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py index 0fd8ed8f33..c31fabce69 100644 --- a/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py +++ b/tests/test_tutorial/test_multiple_values/test_arguments_with_multiple_values/test_tutorial002.py @@ -27,7 +27,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "[OPTIONS] [NAMES]..." in result.output + assert "[OPTIONS] [names]..." in result.output assert "Arguments" in result.output assert "[default: Harry, Hermione, Ron]" in result.output diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial003.py b/tests/test_tutorial/test_options/test_help/test_tutorial003.py index de99469dfa..4bb1cc10a9 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial003.py @@ -32,7 +32,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--fullname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[default: Wade Wilson]" not in result.output diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial004.py b/tests/test_tutorial/test_options/test_help/test_tutorial004.py index 22f902197b..5936ebca97 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial004.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial004.py @@ -34,7 +34,7 @@ def test_help(monkeypatch, mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--fullname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[default: (Deadpoolio the amazing's name)]" in result.output diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial001.py b/tests/test_tutorial/test_options/test_name/test_tutorial001.py index 1c4f2a7cf0..d375a92bfd 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial001.py @@ -26,7 +26,7 @@ def test_option_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--name" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "--user-name" not in result.output diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial002.py b/tests/test_tutorial/test_options/test_name/test_tutorial002.py index ac9b3db6f1..9e0dcb4892 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial002.py @@ -27,7 +27,7 @@ def test_option_help(mod: ModuleType): assert result.exit_code == 0 assert "-n" in result.output assert "--name" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "--user-name" not in result.output diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial003.py b/tests/test_tutorial/test_options/test_name/test_tutorial003.py index 0503b410af..e20ca92a63 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial003.py @@ -26,7 +26,7 @@ def test_option_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "-n" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "--user-name" not in result.output assert "--name" not in result.output diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial004.py b/tests/test_tutorial/test_options/test_name/test_tutorial004.py index f200021042..862890b9c7 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial004.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial004.py @@ -27,7 +27,7 @@ def test_option_help(mod: ModuleType): assert result.exit_code == 0 assert "-n" in result.output assert "--user-name" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "--name" not in result.output diff --git a/tests/test_tutorial/test_options/test_name/test_tutorial005.py b/tests/test_tutorial/test_options/test_name/test_tutorial005.py index 492a0fc4ef..520073b98e 100644 --- a/tests/test_tutorial/test_options/test_name/test_tutorial005.py +++ b/tests/test_tutorial/test_options/test_name/test_tutorial005.py @@ -27,7 +27,7 @@ def test_option_help(mod: ModuleType): assert result.exit_code == 0 assert "-n" in result.output assert "--name" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "-f" in result.output assert "--formal" in result.output diff --git a/tests/test_tutorial/test_options/test_password/test_tutorial001.py b/tests/test_tutorial/test_options/test_password/test_tutorial001.py index 4aca1c0bd8..8374a497a3 100644 --- a/tests/test_tutorial/test_options/test_password/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_password/test_tutorial001.py @@ -44,7 +44,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 output_without_double_spaces = strip_double_spaces(result.output) - assert "--email TEXT [required]" in output_without_double_spaces + assert "--email [required]" in output_without_double_spaces def test_script(mod: ModuleType): diff --git a/tests/test_tutorial/test_options/test_password/test_tutorial002.py b/tests/test_tutorial/test_options/test_password/test_tutorial002.py index 08d43ff87e..4b63dbc20c 100644 --- a/tests/test_tutorial/test_options/test_password/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_password/test_tutorial002.py @@ -48,7 +48,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 output_without_double_spaces = strip_double_spaces(result.output) - assert "--password TEXT [required]" in output_without_double_spaces + assert "--password [required]" in output_without_double_spaces def test_script(mod: ModuleType): diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py index 1236f33e57..c0d1e5770c 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial001.py @@ -39,7 +39,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py index 0947a5e77e..42def22bd6 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial002.py @@ -39,7 +39,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py index 6016dc4acf..daefde09fa 100644 --- a/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py +++ b/tests/test_tutorial/test_options/test_prompt/test_tutorial003.py @@ -48,7 +48,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--project-name" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py index 72ad6e04cd..5003c80ae3 100644 --- a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py @@ -41,7 +41,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[required]" in result.output @@ -50,7 +50,7 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output - assert "TEXT" in result.output + assert "" in result.output assert "[required]" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py index eea63c5a8b..ba9ac4f5e9 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py @@ -20,7 +20,7 @@ def test_type_repr(): def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 - assert "[%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S]" in result.output + assert "<%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S>" in result.output def test_main(): diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py index 6ec636d7ec..a27d32f1bb 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial001.py @@ -13,7 +13,7 @@ def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--network" in result.output - assert "[simple|conv|lstm]" in result.output + assert "" in result.output assert "default: simple" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py index d6c0e532c9..0bc6453dba 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py @@ -26,7 +26,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--groceries" in result.output - assert "[Eggs|Bacon|Cheese]" in result.output + assert "" in result.output assert "default: Eggs, Cheese" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py index 84f0eb3b16..0791fab333 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial004.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "--network [simple|conv|lstm]" in result.output.replace(" ", "") + assert "--network " in result.output.replace(" ", "") def test_main(mod): diff --git a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py index ee0daa9f06..196e5b10b6 100644 --- a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py @@ -24,9 +24,9 @@ def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "--age" in result.output - assert "INTEGER" in result.output + assert "" in result.output assert "--height-meters" in result.output - assert "FLOAT" in result.output + assert "" in result.output def test_params(): diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index ffe3ad09a0..177ea43764 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -41,9 +41,9 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--age" in result.output - assert "INTEGER RANGE" in result.output + assert "int range" in result.output assert "--score" in result.output - assert "FLOAT RANGE" in result.output + assert "float range" in result.output def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): @@ -51,9 +51,9 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--age" in result.output - assert "INTEGER RANGE" in result.output + assert "int range" in result.output assert "--score" in result.output - assert "FLOAT RANGE" in result.output + assert "float range" in result.output def test_params(mod: ModuleType): diff --git a/tests/test_tutorial/test_typer_app/test_tutorial001.py b/tests/test_tutorial/test_typer_app/test_tutorial001.py index a951fe1881..175841b304 100644 --- a/tests/test_tutorial/test_typer_app/test_tutorial001.py +++ b/tests/test_tutorial/test_typer_app/test_tutorial001.py @@ -13,7 +13,7 @@ def test_no_arg(): result = runner.invoke(app) assert result.exit_code != 0 - assert "Missing argument 'NAME'." in result.output + assert "Missing argument 'name'." in result.output def test_arg(): diff --git a/tests/test_types.py b/tests/test_types.py index db6dae08da..aa97c3ca68 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -93,11 +93,11 @@ def test_enum_choice_repr() -> None: def test_enum_choice_help() -> None: result = runner.invoke(app, ["hello-argument", "--help"]) assert result.exit_code == 0 - assert "{rick|morty}" in result.output + assert "" in result.output result = runner.invoke(app, ["hello-option", "--help"]) assert result.exit_code == 0 - assert "[rick|morty]" in result.output + assert "" in result.output result = runner.invoke(app, ["hello-no-choices", "--help"]) assert result.exit_code == 0 From fc37d3af0bee40b81f3d307deda033f194b7b7f9 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 11:12:15 +0200 Subject: [PATCH 02/29] remove upper --- typer/_click/core.py | 2 +- typer/_types.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/typer/_click/core.py b/typer/_click/core.py index 580b558b9f..6f039265ce 100644 --- a/typer/_click/core.py +++ b/typer/_click/core.py @@ -885,7 +885,7 @@ def make_metavar(self, ctx: Context) -> str: metavar = self.type.get_metavar(param=self, ctx=ctx) if metavar is None: - metavar = self.type.name.upper() + metavar = self.type.name if self.nargs != 1: metavar += "..." diff --git a/typer/_types.py b/typer/_types.py index 09b38afb3f..356e92e762 100644 --- a/typer/_types.py +++ b/typer/_types.py @@ -50,7 +50,7 @@ def normalize_choice( def get_metavar(self, param: _click.Parameter, ctx: _click.Context) -> str | None: if param.param_type_name == "option" and not param.show_choices: # type: ignore choice_metavars = [ - types.convert_type(type(choice)).name.upper() for choice in self.choices + types.convert_type(type(choice)).name for choice in self.choices ] choices_str = "|".join([*dict.fromkeys(choice_metavars)]) else: From a3e01362a49735701264d775bc28741fc834d780 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 11:13:13 +0200 Subject: [PATCH 03/29] unify type names to Python types --- typer/_click/types.py | 6 +++--- typer/core.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/typer/_click/types.py b/typer/_click/types.py index 5ccf15fe1b..3375363002 100644 --- a/typer/_click/types.py +++ b/typer/_click/types.py @@ -142,7 +142,7 @@ def convert( class StringParamType(ParamType): - name = "text" + name = "str" def convert( self, value: Any, param: Union["Parameter", None], ctx: Union["Context", None] @@ -310,7 +310,7 @@ def __repr__(self) -> str: class IntParamType(_NumberParamTypeBase): - name = "integer" + name = "int" _number_class = int def __repr__(self) -> str: @@ -328,7 +328,7 @@ class IntRange(_NumberRangeBase, IntParamType): boundary instead of failing. """ - name = "integer range" + name = "int range" def _clamp( # type: ignore self, bound: int, dir: Literal[1, -1], open: bool diff --git a/typer/core.py b/typer/core.py index 6868ab4355..e1339b8d40 100644 --- a/typer/core.py +++ b/typer/core.py @@ -303,7 +303,7 @@ def human_readable_name(self) -> str: if self.metavar is not None: return self.metavar assert self.name is not None, "self.name or self.metavar should be set" - return self.name.upper() + return self.name def _get_default_string( self, @@ -388,7 +388,7 @@ def make_metavar(self, ctx: _click.Context) -> str: if not self.required and not var.startswith("["): var = f"[{var}]" return var - var = (self.name or "").upper() + var = self.name or "" if not self.required: var = f"[{var}]" type_var = self.type.get_metavar(self, ctx=ctx) From 121c30713701cbac851964698e365c177c73e498 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 11:13:31 +0200 Subject: [PATCH 04/29] choices with <> --- typer/_click/types.py | 2 +- typer/_types.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/typer/_click/types.py b/typer/_click/types.py index 3375363002..f49244c6c5 100644 --- a/typer/_click/types.py +++ b/typer/_click/types.py @@ -193,7 +193,7 @@ def __init__(self, formats: Sequence[str] | None = None): ] def get_metavar(self, param: "Parameter", ctx: "Context") -> str | None: - return f"[{'|'.join(self.formats)}]" + return f"<{'|'.join(self.formats)}>" def _try_to_convert_date(self, value: Any, format: str) -> datetime | None: try: diff --git a/typer/_types.py b/typer/_types.py index 356e92e762..26086fb270 100644 --- a/typer/_types.py +++ b/typer/_types.py @@ -58,12 +58,8 @@ def get_metavar(self, param: _click.Parameter, ctx: _click.Context) -> str | Non [str(i) for i in self._normalized_mapping(ctx=ctx).values()] ) - # Use curly braces to indicate a required argument. - if param.required and param.param_type_name == "argument": - return f"{{{choices_str}}}" - - # Use square braces to indicate an option or optional argument. - return f"[{choices_str}]" + # Use square braces as it's a type. + return f"<{choices_str}>" def get_missing_message( self, param: _click.Parameter, ctx: _click.Context | None From bb1969361347695aa26385829bde9f58fc04fcd0 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 15:02:02 +0200 Subject: [PATCH 05/29] add {} when argument is required --- typer/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/typer/core.py b/typer/core.py index e1339b8d40..821181206d 100644 --- a/typer/core.py +++ b/typer/core.py @@ -387,10 +387,12 @@ def make_metavar(self, ctx: _click.Context) -> str: var = self.metavar if not self.required and not var.startswith("["): var = f"[{var}]" - return var + return f"{{{var}}}" var = self.name or "" if not self.required: var = f"[{var}]" + else: + var = f"{{{var}}}" type_var = self.type.get_metavar(self, ctx=ctx) if type_var: var += f":{type_var}" From d9c5943837241c618780090eb42df1e082e48b61 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 15:12:30 +0200 Subject: [PATCH 06/29] add <> around the metavar type --- typer/_click/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typer/_click/core.py b/typer/_click/core.py index 6f039265ce..d7bdf77099 100644 --- a/typer/_click/core.py +++ b/typer/_click/core.py @@ -885,7 +885,7 @@ def make_metavar(self, ctx: Context) -> str: metavar = self.type.get_metavar(param=self, ctx=ctx) if metavar is None: - metavar = self.type.name + metavar = f"<{self.type.name}>" if self.nargs != 1: metavar += "..." From 71861611704a7f65190349fb2e181a2f84f2702e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 15:39:45 +0200 Subject: [PATCH 07/29] avoid lowercasing the parameters at declaration --- tests/test_core.py | 2 +- typer/core.py | 4 ++-- typer/main.py | 13 ++++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index c3920ab883..32a9aeafd1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -25,7 +25,7 @@ def main( command = typer.main.get_command(app) params = {param.name: param for param in command.params} - assert params["my_arg_1"].human_readable_name == "MY_ARG_1" + assert params["my_arg_1"].human_readable_name == "my_arg_1" assert params["my_arg_2"].human_readable_name == "META_ARG" assert params["my_opt"].human_readable_name == "my_opt" diff --git a/typer/core.py b/typer/core.py index 821181206d..2314ad501c 100644 --- a/typer/core.py +++ b/typer/core.py @@ -412,7 +412,7 @@ def _parse_decls( raise TypeError("Argument is marked as exposed, but does not have a name.") if len(decls) == 1: name = arg = decls[0] - name = name.replace("-", "_").lower() + name = name.replace("-", "_") else: raise TypeError( "Arguments take exactly one parameter declaration, got" @@ -577,7 +577,7 @@ def _parse_decls( if name is None and possible_names: possible_names.sort(key=lambda x: -len(x[0])) # group long options first - name = possible_names[0][1].replace("-", "_").lower() + name = possible_names[0][1].replace("-", "_") if not name.isidentifier(): name = None diff --git a/typer/main.py b/typer/main.py index a825c1b14e..700648da66 100644 --- a/typer/main.py +++ b/typer/main.py @@ -1361,6 +1361,15 @@ def get_command_name(name: str) -> str: return name.lower().replace("_", "-") +def get_default_option_flag_name(name: str, metavar: str | None) -> str: + flag_name = name.replace("_", "-") + if metavar is not None: + meta_flag = metavar.replace("_", "-") + if meta_flag.lower() == flag_name.lower(): + return meta_flag + return flag_name + + def get_params_convertors_ctx_param_name_from_function( callback: Callable[..., Any] | None, ) -> tuple[list[TyperArgument | TyperOption], dict[str, Any], str | None]: @@ -1699,7 +1708,9 @@ def get_click_param( # Click doesn't accept a flag of type bool, only None, and then it sets it # to bool internally parameter_type = None - default_option_name = get_command_name(param.name) + default_option_name = get_default_option_flag_name( + param.name, parameter_info.metavar + ) if is_flag: default_option_declaration = ( f"--{default_option_name}/--no-{default_option_name}" From d59858af7c56644f36296ca509845ee99ca2bdd3 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 15:44:51 +0200 Subject: [PATCH 08/29] avoid two types of brackets --- typer/core.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/typer/core.py b/typer/core.py index 2314ad501c..4688d99c04 100644 --- a/typer/core.py +++ b/typer/core.py @@ -385,8 +385,10 @@ def make_metavar(self, ctx: _click.Context) -> str: # to include Argument name if self.metavar is not None: var = self.metavar - if not self.required and not var.startswith("["): - var = f"[{var}]" + if var.startswith("["): + return var + if not self.required: + return f"[{var}]" return f"{{{var}}}" var = self.name or "" if not self.required: From c0c90c9488157d43175d11430a0b89ed4ef1e90c Mon Sep 17 00:00:00 2001 From: svlandeg Date: Sat, 27 Jun 2026 15:56:40 +0200 Subject: [PATCH 09/29] fix arg display in help --- typer/rich_utils.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/typer/rich_utils.py b/typer/rich_utils.py index de68f60644..adb76828c4 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -370,13 +370,18 @@ def _print_options_panel( metavar_type = None metavar_str = param.make_metavar(ctx=ctx) if isinstance(param, TyperArgument): - # TODO: revise this legacy behaviour of keeping argument names lowercased for Rich formatting - if param.metavar is None and param.name: - metavar_name = metavar_str.replace(param.name.upper(), param.name) + if param.metavar is not None: + metavar_name = param.metavar else: - metavar_name = metavar_str + metavar_name = param.name or "" + if not param.required: + metavar_name = f"[{metavar_name}]" if isinstance(param, TyperOption): metavar_type = metavar_str + elif isinstance(param, TyperArgument): + metavar_type = param.type.get_metavar(param=param, ctx=ctx) + if metavar_type is None: + metavar_type = f"<{param.type.name}>" for opt_str in param.opts: if "--" in opt_str: @@ -399,10 +404,6 @@ def _print_options_panel( # Fetch type if metavar_type and metavar_type != "BOOLEAN": types_data.append(metavar_type) - else: - type_str = param.type.name.upper() - if type_str != "BOOLEAN": - types_data.append(type_str) # Range - from # https://github.com/pallets/click/blob/c63c70dabd3f86ca68678b4f00951f78f52d0270/src/click/core.py#L2698-L2706 # noqa: E501 From 9c8aaa7c8fc1e11c563e17ded15a04aa72917b31 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 7 Jul 2026 23:10:14 +0200 Subject: [PATCH 10/29] change metavar display depending on being in usage line or not --- typer/core.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/typer/core.py b/typer/core.py index 4688d99c04..5c6d9f2097 100644 --- a/typer/core.py +++ b/typer/core.py @@ -380,7 +380,7 @@ def get_help_record(self, ctx: _click.Context) -> tuple[str, str] | None: help = f"{help} {extra_str}" if help else f"{extra_str}" return name, help - def make_metavar(self, ctx: _click.Context) -> str: + def make_metavar(self, ctx: _click.Context, *, usage: bool = False) -> str: # Modified version of _click.core.Argument.make_metavar() # to include Argument name if self.metavar is not None: @@ -389,11 +389,13 @@ def make_metavar(self, ctx: _click.Context) -> str: return var if not self.required: return f"[{var}]" - return f"{{{var}}}" + if usage: + return f"{{{var}}}" + return var var = self.name or "" if not self.required: var = f"[{var}]" - else: + elif usage: var = f"{{{var}}}" type_var = self.type.get_metavar(self, ctx=ctx) if type_var: @@ -423,7 +425,7 @@ def _parse_decls( return name, [arg], [] def get_usage_pieces(self, ctx: _click.Context) -> list[str]: - return [self.make_metavar(ctx)] + return [self.make_metavar(ctx, usage=True)] def get_error_hint(self, ctx: _click.Context) -> str: return f"'{self.make_metavar(ctx)}'" From 15243764034d7afcc90c2240dc72fe709ca0e3f5 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 7 Jul 2026 23:23:46 +0200 Subject: [PATCH 11/29] fix test --- tests/test_others.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_others.py b/tests/test_others.py index d2cc8696f1..ade64750f7 100644 --- a/tests/test_others.py +++ b/tests/test_others.py @@ -450,7 +450,8 @@ def main(arg1, arg2: int, arg3: "int", arg4: bool = False, arg5: "bool" = False) result = runner.invoke(app, ["Hello", "2", "invalid"]) - assert "Invalid value for 'ARG3': 'invalid' is not a valid integer" in result.output + assert "Invalid value for 'arg3'" in result.output + assert "'invalid' is not a valid int" in result.output result = runner.invoke(app, ["Hello", "2", "3", "--arg4", "--arg5"]) assert ( "arg1: Hello\narg2: 2\narg3: 3\narg4: True\narg5: True\n" From 80f5461d3744fceb78b9fca8a38d0280c822533d Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 00:13:52 +0200 Subject: [PATCH 12/29] use human_readable_name for error hint --- .../test_parameter_types/test_datetime/test_tutorial001.py | 5 +---- typer/core.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py index ba9ac4f5e9..20c939c90b 100644 --- a/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_datetime/test_tutorial001.py @@ -42,10 +42,7 @@ def test_main_datetime_object(): def test_invalid(): result = runner.invoke(app, ["july-19-1989"]) assert result.exit_code != 0 - assert ( - "Invalid value for 'BIRTH:[%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S]':" - in result.output - ) + assert "Invalid value for 'birth'" in result.output assert "'july-19-1989' does not match the formats" in result.output assert "%Y-%m-%d" in result.output assert "%Y-%m-%dT%H:%M:%S" in result.output diff --git a/typer/core.py b/typer/core.py index 5c6d9f2097..9b6e0ecac1 100644 --- a/typer/core.py +++ b/typer/core.py @@ -428,7 +428,7 @@ def get_usage_pieces(self, ctx: _click.Context) -> list[str]: return [self.make_metavar(ctx, usage=True)] def get_error_hint(self, ctx: _click.Context) -> str: - return f"'{self.make_metavar(ctx)}'" + return f"'{self.human_readable_name}'" def add_to_parser(self, parser: _OptionParser, ctx: _click.Context) -> None: parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) From 6a4aef8521c8d0c7668c5adfa9b2236f3857a5e1 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 00:24:16 +0200 Subject: [PATCH 13/29] fix enum display --- docs/tutorial/parameter-types/enum.md | 12 ++++++------ .../test_enum/test_tutorial003.py | 2 +- .../test_index/test_tutorial001.py | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md index 185ad420c3..bfa5d53aee 100644 --- a/docs/tutorial/parameter-types/enum.md +++ b/docs/tutorial/parameter-types/enum.md @@ -19,11 +19,11 @@ Check it: ```console $ python main.py --help -// Notice the predefined values [simple|conv|lstm] +// Notice the predefined values Usage: main.py [OPTIONS] Options: - --network [simple|conv|lstm] [default: simple] + --network [default: simple] --help Show this message and exit. // Try it @@ -91,8 +91,8 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - --groceries [Eggs|Bacon|Cheese] [default: Eggs, Cheese] - --help Show this message and exit. + --groceries [default: Eggs, Cheese] + --help Show this message and exit. // Try it with the default values $ python main.py @@ -123,11 +123,11 @@ You can also use `Literal` to represent a set of possible predefined choices, wi ```console $ python main.py --help -// Notice the predefined values [simple|conv|lstm] +// Notice the predefined values Usage: main.py [OPTIONS] Options: - --network [simple|conv|lstm] [default: simple] + --network [default: simple] --help Show this message and exit. // Try it diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py index 0bc6453dba..03ffd9c990 100644 --- a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py +++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py @@ -26,7 +26,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--groceries" in result.output - assert "" in result.output + assert "" in result.output assert "default: Eggs, Cheese" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py index 196e5b10b6..8d7fdae4f7 100644 --- a/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_index/test_tutorial001.py @@ -44,7 +44,7 @@ def test_invalid(): result = runner.invoke(app, ["Camila", "--age", "15.3"]) assert result.exit_code != 0 assert "Invalid value for '--age'" in result.output - assert "'15.3' is not a valid integer" in result.output + assert "'15.3' is not a valid int." in result.output def test_script(): From 43a8137f0e66fb6690791c4f7397ef5a348577af Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 00:24:34 +0200 Subject: [PATCH 14/29] make ID uppercase var in the docs --- docs_src/parameter_types/number/tutorial001_an_py310.py | 4 ++-- docs_src/parameter_types/number/tutorial001_py310.py | 4 ++-- docs_src/parameter_types/number/tutorial002_an_py310.py | 4 ++-- docs_src/parameter_types/number/tutorial002_py310.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs_src/parameter_types/number/tutorial001_an_py310.py b/docs_src/parameter_types/number/tutorial001_an_py310.py index 1784b13f06..995f64b67f 100644 --- a/docs_src/parameter_types/number/tutorial001_an_py310.py +++ b/docs_src/parameter_types/number/tutorial001_an_py310.py @@ -7,11 +7,11 @@ @app.command() def main( - id: Annotated[int, typer.Argument(min=0, max=1000)], + ID: Annotated[int, typer.Argument(min=0, max=1000)], age: Annotated[int, typer.Option(min=18)] = 20, score: Annotated[float, typer.Option(max=100)] = 0, ): - print(f"ID is {id}") + print(f"ID is {ID}") print(f"--age is {age}") print(f"--score is {score}") diff --git a/docs_src/parameter_types/number/tutorial001_py310.py b/docs_src/parameter_types/number/tutorial001_py310.py index fc4fe0d30e..37e9e39ff8 100644 --- a/docs_src/parameter_types/number/tutorial001_py310.py +++ b/docs_src/parameter_types/number/tutorial001_py310.py @@ -5,11 +5,11 @@ @app.command() def main( - id: int = typer.Argument(..., min=0, max=1000), + ID: int = typer.Argument(..., min=0, max=1000), age: int = typer.Option(20, min=18), score: float = typer.Option(0, max=100), ): - print(f"ID is {id}") + print(f"ID is {ID}") print(f"--age is {age}") print(f"--score is {score}") diff --git a/docs_src/parameter_types/number/tutorial002_an_py310.py b/docs_src/parameter_types/number/tutorial002_an_py310.py index 5d3835817c..9df5e4838e 100644 --- a/docs_src/parameter_types/number/tutorial002_an_py310.py +++ b/docs_src/parameter_types/number/tutorial002_an_py310.py @@ -7,11 +7,11 @@ @app.command() def main( - id: Annotated[int, typer.Argument(min=0, max=1000)], + ID: Annotated[int, typer.Argument(min=0, max=1000)], rank: Annotated[int, typer.Option(max=10, clamp=True)] = 0, score: Annotated[float, typer.Option(min=0, max=100, clamp=True)] = 0, ): - print(f"ID is {id}") + print(f"ID is {ID}") print(f"--rank is {rank}") print(f"--score is {score}") diff --git a/docs_src/parameter_types/number/tutorial002_py310.py b/docs_src/parameter_types/number/tutorial002_py310.py index c0daadfbd5..f4a624619f 100644 --- a/docs_src/parameter_types/number/tutorial002_py310.py +++ b/docs_src/parameter_types/number/tutorial002_py310.py @@ -5,11 +5,11 @@ @app.command() def main( - id: int = typer.Argument(..., min=0, max=1000), + ID: int = typer.Argument(..., min=0, max=1000), rank: int = typer.Option(0, max=10, clamp=True), score: float = typer.Option(0, min=0, max=100, clamp=True), ): - print(f"ID is {id}") + print(f"ID is {ID}") print(f"--rank is {rank}") print(f"--score is {score}") From 87a70d37c336bca6697f9adcfc585eff52721b5b Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 00:31:08 +0200 Subject: [PATCH 15/29] few more small fixes --- .../test_parameter_types/test_number/test_tutorial001.py | 2 +- .../test_parameter_types/test_uuid/test_tutorial001.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index 177ea43764..466bc55d1c 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -27,7 +27,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_type_repr(mod: ModuleType): command = typer.main.get_command(mod.app) - id_param = next(param for param in command.params if param.name == "id") + id_param = next(param for param in command.params if param.name == "ID") assert repr(id_param.type) == "" age_param = next(param for param in command.params if param.name == "age") diff --git a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py index 7b79e81405..2bf7bb10ef 100644 --- a/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_uuid/test_tutorial001.py @@ -35,10 +35,8 @@ def test_main_with_uuid_object(): def test_invalid_uuid(): result = runner.invoke(app, ["7479706572-72756c6573"]) assert result.exit_code != 0 - assert ( - "Invalid value for 'USER_ID': '7479706572-72756c6573' is not a valid UUID" - in result.output - ) + assert "Invalid value for 'user_id'" in result.output + assert "not a valid UUID" in result.output def test_script(): From 4daef8cb8d1d79779865202a744a5921d94a2b2e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 11:10:32 +0200 Subject: [PATCH 16/29] add test_param_type_help_metavar test --- tests/test_type_conversion.py | 50 ++++++++++++++++++++++++++++++++++- typer/_click/core.py | 6 ++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/tests/test_type_conversion.py b/tests/test_type_conversion.py index 26709db0e2..29b5e412ab 100644 --- a/tests/test_type_conversion.py +++ b/tests/test_type_conversion.py @@ -1,7 +1,8 @@ +from datetime import datetime import os from enum import Enum from pathlib import Path -from typing import Any +from typing import Any, Annotated, Literal import pytest import typer @@ -398,3 +399,50 @@ def __init__(self, encoding: str | None) -> None: converted = _click.types.STRING.convert(b"\xff", None, None) assert converted == "ÿ" + + +@pytest.mark.parametrize( + ("parameter", "expected_metavar"), + [ + pytest.param(Annotated[str, typer.Option(...)], ""), + pytest.param(Annotated[str, typer.Argument(...)], ""), + pytest.param(Annotated[int, typer.Option(...)], ""), + pytest.param(Annotated[int, typer.Argument(...)], ""), + pytest.param(Annotated[float, typer.Option(...)], ""), + pytest.param( + Annotated[float, typer.Option(..., min=0.666, max=3.42)], "" + ), + pytest.param(Annotated[tuple[str, int], typer.Option(...)], "..."), + pytest.param(Annotated[tuple[Path, str], typer.Option(...)], "..."), + pytest.param(Annotated[str, typer.Option(..., resolve_path=True)], ""), + pytest.param(Annotated[Path, typer.Option(...)], ""), + pytest.param(Annotated[Path, typer.Option(..., dir_okay=False)], ""), + pytest.param(Annotated[Path, typer.Option(..., file_okay=False)], ""), + pytest.param(Annotated[SomeEnum, typer.Option(...)], ""), + pytest.param(Annotated[SomeEnum, typer.Argument()], ""), + pytest.param(Annotated[Literal["x", "y"], typer.Option(...)], ""), + pytest.param( + Annotated[datetime, typer.Option(..., formats=["%Y-%m-%d", "%d/%m/%Y"])], + "<%Y-%m-%d|%d/%m/%Y>", + ), + ], +) +def test_param_type_help_metavar(parameter: Any, expected_metavar: str) -> None: + app = typer.Typer() + + @app.command() + # TODO: type-specific default + def with_default(value: parameter = "my_default"): + pass # pragma: no cover + + @app.command() + def without_default(value: parameter): + pass # pragma: no cover + + result = runner.invoke(app, ["with-default", "--help"]) + assert result.exit_code == 0 + assert expected_metavar in result.output + + result = runner.invoke(app, ["without-default", "--help"]) + assert result.exit_code == 0 + assert expected_metavar in result.output \ No newline at end of file diff --git a/typer/_click/core.py b/typer/_click/core.py index d7bdf77099..85486e3526 100644 --- a/typer/_click/core.py +++ b/typer/_click/core.py @@ -885,7 +885,11 @@ def make_metavar(self, ctx: Context) -> str: metavar = self.type.get_metavar(param=self, ctx=ctx) if metavar is None: - metavar = f"<{self.type.name}>" + type_name = self.type.name + if type_name.startswith("<") and type_name.endswith(">"): + metavar = type_name + else: + metavar = f"<{type_name}>" if self.nargs != 1: metavar += "..." From 7c19318002506325d72a59d7af76ee8545da5cfb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:11:11 +0000 Subject: [PATCH 17/29] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_type_conversion.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_type_conversion.py b/tests/test_type_conversion.py index 29b5e412ab..18865eea31 100644 --- a/tests/test_type_conversion.py +++ b/tests/test_type_conversion.py @@ -1,8 +1,8 @@ -from datetime import datetime import os +from datetime import datetime from enum import Enum from pathlib import Path -from typing import Any, Annotated, Literal +from typing import Annotated, Any, Literal import pytest import typer @@ -417,7 +417,9 @@ def __init__(self, encoding: str | None) -> None: pytest.param(Annotated[str, typer.Option(..., resolve_path=True)], ""), pytest.param(Annotated[Path, typer.Option(...)], ""), pytest.param(Annotated[Path, typer.Option(..., dir_okay=False)], ""), - pytest.param(Annotated[Path, typer.Option(..., file_okay=False)], ""), + pytest.param( + Annotated[Path, typer.Option(..., file_okay=False)], "" + ), pytest.param(Annotated[SomeEnum, typer.Option(...)], ""), pytest.param(Annotated[SomeEnum, typer.Argument()], ""), pytest.param(Annotated[Literal["x", "y"], typer.Option(...)], ""), @@ -445,4 +447,4 @@ def without_default(value: parameter): result = runner.invoke(app, ["without-default", "--help"]) assert result.exit_code == 0 - assert expected_metavar in result.output \ No newline at end of file + assert expected_metavar in result.output From 95d4ca48e8361742de4158fc5d4efe4ea601d56b Mon Sep 17 00:00:00 2001 From: svlandeg Date: Wed, 8 Jul 2026 11:39:55 +0200 Subject: [PATCH 18/29] fix coverage --- tests/test_type_conversion.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_type_conversion.py b/tests/test_type_conversion.py index 18865eea31..bf42268818 100644 --- a/tests/test_type_conversion.py +++ b/tests/test_type_conversion.py @@ -448,3 +448,16 @@ def without_default(value: parameter): result = runner.invoke(app, ["without-default", "--help"]) assert result.exit_code == 0 assert expected_metavar in result.output + + +def test_metavar_preformatted_square_brackets() -> None: + app = typer.Typer() + + @app.command() + def main(value: Annotated[str, typer.Argument(metavar="[VALUE]")]): + pass # pragma: no cover + + result = runner.invoke(app, ["--help"]) + assert result.exit_code == 0 + assert "[VALUE]" in result.output + assert "[[VALUE]]" not in result.output From 3e6c575113fe7d22ab73153c47269a7242cae2f3 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 11:18:07 +0200 Subject: [PATCH 19/29] fix miminum example file from tutorial not showing [PATH_OR_MODULE] --- tests/assets/cli/minimum_main.py | 8 ++++++++ tests/test_cli/test_help.py | 15 +++++++++++++++ typer/cli.py | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/assets/cli/minimum_main.py diff --git a/tests/assets/cli/minimum_main.py b/tests/assets/cli/minimum_main.py new file mode 100644 index 0000000000..e8085d931e --- /dev/null +++ b/tests/assets/cli/minimum_main.py @@ -0,0 +1,8 @@ +import typer + +app = typer.Typer() + + +@app.callback() +def main(name: str) -> None: + pass diff --git a/tests/test_cli/test_help.py b/tests/test_cli/test_help.py index 3238c0658b..3bad9035e1 100644 --- a/tests/test_cli/test_help.py +++ b/tests/test_cli/test_help.py @@ -157,3 +157,18 @@ def cmd( "Description is rendered in the next line for long option labels." in continuation_block ) + + +def test_typer_run_usage() -> None: + from typer.cli import app as typer_cli_app + + result = runner.invoke( + typer_cli_app, + ["tests/assets/cli/minimum_main.py", "run"], + prog_name="typer", + ) + + assert result.exit_code == 2 + usage_line = result.output.splitlines()[0] + assert usage_line.startswith("Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name}") + assert "Try 'typer [PATH_OR_MODULE] run --help' for help." in result.output diff --git a/typer/cli.py b/typer/cli.py index 665bcf5a59..98f9f4ec77 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -161,7 +161,7 @@ def print_version(ctx: _click.Context, param: TyperOption, value: bool) -> None: def callback( ctx: typer.Context, *, - path_or_module: str = typer.Argument(None), + path_or_module: str = typer.Argument(None, metavar="PATH_OR_MODULE"), app: str = typer.Option(None, help="The typer app object/variable to use."), func: str = typer.Option(None, help="The function to convert to Typer."), version: bool = typer.Option( From 16988d7a01d4fe3a0187fd85250f50be24a5c8f6 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 11:27:03 +0200 Subject: [PATCH 20/29] fix coverage --- tests/assets/cli/minimum_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/assets/cli/minimum_main.py b/tests/assets/cli/minimum_main.py index e8085d931e..3bd9c5c84d 100644 --- a/tests/assets/cli/minimum_main.py +++ b/tests/assets/cli/minimum_main.py @@ -5,4 +5,4 @@ @app.callback() def main(name: str) -> None: - pass + pass # pragma: no cover From 135187ecc275c1259d1273b1608561920eb55639 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 11:34:15 +0200 Subject: [PATCH 21/29] ensure Rich doesn't swallow a lowercased path_or_module annotation --- tests/test_rich_utils.py | 20 ++++++++++++++++++++ typer/rich_utils.py | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/test_rich_utils.py b/tests/test_rich_utils.py index 6d11652d77..da0a23c4dd 100644 --- a/tests/test_rich_utils.py +++ b/tests/test_rich_utils.py @@ -266,3 +266,23 @@ def main( assert "--arg2" in out_nospace assert "--ARG5" in out_nospace assert "--arg6" in out_nospace + + +def test_rich_lowercase_bracketed_metavar() -> None: + # Make sure Rich doesn't "swallow" a lowercased [path] (thinking it's a Rich annotation) + app = typer.Typer(rich_markup_mode="rich") + + @app.callback() + def main(path_or_module: str = typer.Argument(None)) -> None: + pass # pragma: no cover + + @app.command() + def run(name: str) -> None: + pass # pragma: no cover + + result = runner.invoke(app, ["my-module.py", "run"], prog_name="typer") + + assert result.exit_code == 2 + usage_line = result.output.splitlines()[0] + assert usage_line.startswith("Usage: typer [path_or_module] run [OPTIONS] {name}") + assert "Try 'typer [path_or_module] run --help' for help." in result.output diff --git a/typer/rich_utils.py b/typer/rich_utils.py index adb76828c4..9de6ed285a 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -705,12 +705,13 @@ def rich_format_error(self: _click.ClickException) -> None: console = _get_rich_console(stderr=True) ctx: _click.Context | None = getattr(self, "ctx", None) if ctx is not None: - console.print(ctx.get_usage()) + console.print(highlighter(ctx.get_usage()), style=STYLE_USAGE_COMMAND) if ctx is not None and ctx.command.get_help_option(ctx) is not None: console.print( RICH_HELP.format( - command_path=ctx.command_path, help_option=ctx.help_option_names[0] + command_path=escape(ctx.command_path), + help_option=ctx.help_option_names[0], ), style=STYLE_ERRORS_SUGGESTION, ) From 6340753c77f8b88a60d6bbf7eefeee8a9eb1664e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 12:23:56 +0200 Subject: [PATCH 22/29] ensure Rich doesn't print for flags --- tests/test_rich_utils.py | 12 ++++++++++++ typer/rich_utils.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test_rich_utils.py b/tests/test_rich_utils.py index da0a23c4dd..f834c03727 100644 --- a/tests/test_rich_utils.py +++ b/tests/test_rich_utils.py @@ -224,6 +224,18 @@ def find_right_boundary_pos(line): ) +def test_rich_help_no_boolean_type() -> None: + app = typer.Typer(rich_markup_mode="rich") + + @app.command() + def main(name: str) -> None: + pass # pragma: no cover + + result = runner.invoke(app, ["--help"]) + assert result.exit_code == 0 + assert "" not in result.output + + def test_rich_help_metavar(): app = typer.Typer(rich_markup_mode="rich") diff --git a/typer/rich_utils.py b/typer/rich_utils.py index 9de6ed285a..f48b896ca6 100644 --- a/typer/rich_utils.py +++ b/typer/rich_utils.py @@ -402,7 +402,7 @@ def _print_options_panel( types_data = Text(style=STYLE_TYPES, overflow="fold") # Fetch type - if metavar_type and metavar_type != "BOOLEAN": + if metavar_type and "bool" not in metavar_type.lower(): types_data.append(metavar_type) # Range - from From 72b8cd99c0e7f052c0d46943bf1b151eea20ad4a Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 12:32:48 +0200 Subject: [PATCH 23/29] docs fixes (WIP) --- README.md | 28 ++++++++--------- docs/index.md | 28 ++++++++--------- docs/tutorial/arguments/help.md | 6 ++-- docs/tutorial/arguments/optional.md | 4 +-- docs/tutorial/commands/help.md | 12 ++------ docs/tutorial/commands/one-or-multiple.md | 6 ++-- docs/tutorial/first-steps.md | 30 +++++++++---------- docs/tutorial/options/callback-and-context.md | 2 +- docs/tutorial/options/help.md | 10 +++---- docs/tutorial/options/name.md | 10 +++---- docs/tutorial/options/required.md | 6 ++-- docs/tutorial/options/version.md | 2 +- docs/tutorial/parameter-types/index.md | 4 +-- docs/tutorial/typer-app.md | 6 ++-- docs/tutorial/typer-command.md | 4 +-- 15 files changed, 76 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 8f7c49f7eb..ac67ab0e1f 100644 --- a/README.md +++ b/README.md @@ -78,23 +78,23 @@ Run your application with the `typer` command: // Run your application $ typer main.py run -// You get a nice error, you are missing NAME -Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +// You get a nice error, you are missing 'name' +Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Try 'typer [PATH_OR_MODULE] run --help' for help. ╭─ Error ───────────────────────────────────────────╮ -│ Missing argument 'NAME'. │ +│ Missing argument 'name'. │ ╰───────────────────────────────────────────────────╯ // You get a --help for free $ typer main.py run --help -Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Run the provided Typer app. ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] | +│ * name [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -138,21 +138,21 @@ Now you could run it with Python directly: // Run your application $ python main.py -// You get a nice error, you are missing NAME -Usage: main.py [OPTIONS] NAME +// You get a nice error, you are missing 'name' +Usage: main.py [OPTIONS] {name} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ -│ Missing argument 'NAME'. │ +│ Missing argument 'name'. │ ╰───────────────────────────────────────────────────╯ // You get a --help for free $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] | +│ * name [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -254,10 +254,10 @@ Now check the help for the `hello` command: ```console $ python main.py hello --help - Usage: main.py hello [OPTIONS] NAME + Usage: main.py hello [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] │ +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -273,10 +273,10 @@ And now check the help for the `goodbye` command: ```console $ python main.py goodbye --help - Usage: main.py goodbye [OPTIONS] NAME + Usage: main.py goodbye [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] │ +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --formal --no-formal [default: no-formal] │ diff --git a/docs/index.md b/docs/index.md index ac8ef85860..6a06412850 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,23 +86,23 @@ Run your application with the `typer` command: // Run your application $ typer main.py run -// You get a nice error, you are missing NAME -Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +// You get a nice error, you are missing 'name' +Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Try 'typer [PATH_OR_MODULE] run --help' for help. ╭─ Error ───────────────────────────────────────────╮ -│ Missing argument 'NAME'. │ +│ Missing argument 'name'. │ ╰───────────────────────────────────────────────────╯ // You get a --help for free $ typer main.py run --help -Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME +Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Run the provided Typer app. ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] | +│ * name [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -146,21 +146,21 @@ Now you could run it with Python directly: // Run your application $ python main.py -// You get a nice error, you are missing NAME -Usage: main.py [OPTIONS] NAME +// You get a nice error, you are missing 'name' +Usage: main.py [OPTIONS] {name} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ -│ Missing argument 'NAME'. │ +│ Missing argument 'name'. │ ╰───────────────────────────────────────────────────╯ // You get a --help for free $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] | +│ * name [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -262,10 +262,10 @@ Now check the help for the `hello` command: ```console $ python main.py hello --help - Usage: main.py hello [OPTIONS] NAME + Usage: main.py hello [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] │ +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -281,10 +281,10 @@ And now check the help for the `goodbye` command: ```console $ python main.py goodbye --help - Usage: main.py goodbye [OPTIONS] NAME + Usage: main.py goodbye [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name TEXT [default: None] [required] │ +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --formal --no-formal [default: no-formal] │ diff --git a/docs/tutorial/arguments/help.md b/docs/tutorial/arguments/help.md index 9c390ef874..0882e84747 100644 --- a/docs/tutorial/arguments/help.md +++ b/docs/tutorial/arguments/help.md @@ -22,7 +22,7 @@ And it will be used in the automatic `--help` option: $ python main.py --help // Check the section with Arguments below 🚀 -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Arguments: NAME The name of the user to greet [required] @@ -47,7 +47,7 @@ And the `--help` option will combine all the information: $ python main.py --help // Notice that we have the help text from the docstring and also the Arguments 📝 -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Say hi to NAME very gently, like Dirk. @@ -198,7 +198,7 @@ And next you will see other panels for the *CLI arguments* that have a custom pa ```console $ python main.py --help - Usage: main.py [OPTIONS] NAME [LASTNAME] [AGE] + Usage: main.py [OPTIONS] {name} [LASTNAME] [age] Say hi to NAME very gently, like Dirk. diff --git a/docs/tutorial/arguments/optional.md b/docs/tutorial/arguments/optional.md index 10b03af7b0..62c2d7e311 100644 --- a/docs/tutorial/arguments/optional.md +++ b/docs/tutorial/arguments/optional.md @@ -84,10 +84,10 @@ All we did there achieves the same thing as before, a **required** *CLI argument ```console $ python main.py -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try "main.py --help" for help. -Error: Missing argument 'NAME'. +Error: Missing argument 'name'. ``` diff --git a/docs/tutorial/commands/help.md b/docs/tutorial/commands/help.md index 359339bb78..97492d479a 100644 --- a/docs/tutorial/commands/help.md +++ b/docs/tutorial/commands/help.md @@ -167,7 +167,7 @@ $ python main.py delete --help This is deprecated and will stop being supported soon. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT [default: None] [required] │ +* username TEXT [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --help Show this message and exit. │ @@ -239,7 +239,6 @@ $ python main.py create --help ╭─ Arguments ───────────────────────────────────────────────────────╮ * username TEXT The username to be created │ -│ [default: None] │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -262,7 +261,6 @@ $ python main.py delete --help ╭─ Arguments ───────────────────────────────────────────────────────╮ * username TEXT The username to be deleted │ -│ [default: None] │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -303,7 +301,6 @@ $ python main.py create --help ╭─ Arguments ───────────────────────────────────────────────────────╮ * username TEXT The username to be created │ -│ [default: None] │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -326,7 +323,6 @@ $ python main.py delete --help ╭─ Arguments ───────────────────────────────────────────────────────╮ * username TEXT The username to be deleted │ -│ [default: None] │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -416,7 +412,7 @@ $ python main.py create --help Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to create [default: None] │ +* username TEXT The username to create │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Secondary Arguments ─────────────────────────────────────────────╮ @@ -429,10 +425,8 @@ $ python main.py create --help ╰───────────────────────────────────────────────────────────────────╯ ╭─ Additional Data ─────────────────────────────────────────────────╮ --age INTEGER The age of the new user │ -│ [default: None] │ --favorite-color TEXT The favorite color of the new │ │ user │ -│ [default: None] │ ╰───────────────────────────────────────────────────────────────────╯ ``` @@ -487,7 +481,7 @@ $ python main.py --help Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT [default: None] [required] │ +* username TEXT [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --install-completion Install completion for the current │ diff --git a/docs/tutorial/commands/one-or-multiple.md b/docs/tutorial/commands/one-or-multiple.md index 96f5e3a7de..6af9084fa5 100644 --- a/docs/tutorial/commands/one-or-multiple.md +++ b/docs/tutorial/commands/one-or-multiple.md @@ -12,10 +12,10 @@ You might have noticed that if you create a single command, as in the following // Without a CLI argument $ python main.py -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try "main.py --help" for help. -Error: Missing argument 'NAME'. +Error: Missing argument 'name'. // With the NAME CLI argument $ python main.py Camila @@ -25,7 +25,7 @@ Hello Camila // Asking for help $ python main.py -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Options: --install-completion Install completion for the current shell. diff --git a/docs/tutorial/first-steps.md b/docs/tutorial/first-steps.md index cf1db2d522..ddbc99c7bf 100644 --- a/docs/tutorial/first-steps.md +++ b/docs/tutorial/first-steps.md @@ -70,10 +70,10 @@ Update the previous example with an argument `name`: $ python main.py // If you run it without the argument, it shows a nice error -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ - Missing argument 'NAME'. + Missing argument 'name'. ╰───────────────────────────────────────────────────╯ // Now pass that NAME CLI argument @@ -111,18 +111,18 @@ So, extend that to have 2 arguments, `name` and `lastname`: // Check the main --help $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ - Missing argument 'NAME'. + Missing argument 'name'. ╰───────────────────────────────────────────────────╯ typer on  richify [»!?] via 🐍 v3.7.5 (env3.7) python main.py -Usage: main.py [OPTIONS] NAME LASTNAME +Usage: main.py [OPTIONS] {name} {lastname} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ - Missing argument 'NAME'. + Missing argument 'name'. ╰───────────────────────────────────────────────────╯ // There are now 2 CLI arguments, name and lastname @@ -130,10 +130,10 @@ $ python main.py --help // Now pass a single name argument $ python main.py Camila -Usage: main.py [OPTIONS] NAME LASTNAME +Usage: main.py [OPTIONS] {name} {lastname} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ - Missing argument 'LASTNAME'. + Missing argument 'lastname'. ╰───────────────────────────────────────────────────╯ // These 2 arguments are required, so, pass both: @@ -238,11 +238,11 @@ Here `formal` is a `bool` that is `False` by default. // Get the help $ python main.py --help - Usage: main.py [OPTIONS] NAME LASTNAME + Usage: main.py [OPTIONS] {name} {lastname} ╭─ Arguments ─────────────────────────────────────────────────────╮ -* name TEXT [default: None] [required] │ -* lastname TEXT [default: None] [required] │ +* name TEXT [required] │ +* lastname TEXT [required]╰─────────────────────────────────────────────────────────────────╯ ╭─ Options ───────────────────────────────────────────────────────╮ --formal --no-formal [default: no-formal] │ @@ -298,10 +298,10 @@ As `lastname` now has a default value of `""` (an empty string) it is no longer ```console $ python main.py --help - Usage: main.py [OPTIONS] NAME + Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [default: None] [required] │ +* name TEXT [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --lastname TEXT │ @@ -369,13 +369,13 @@ Now see it with the `--help` option: ```console $ python main.py --help - Usage: main.py [OPTIONS] NAME + Usage: main.py [OPTIONS] {name} Say hi to NAME, optionally with a --lastname. If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [default: None] [required] │ +* name TEXT [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --lastname TEXT │ diff --git a/docs/tutorial/options/callback-and-context.md b/docs/tutorial/options/callback-and-context.md index 53d87ddaf0..33257cedda 100644 --- a/docs/tutorial/options/callback-and-context.md +++ b/docs/tutorial/options/callback-and-context.md @@ -66,7 +66,7 @@ Usage: typer run [OPTIONS] Run the provided Typer app. Options: - --name TEXT [required] + --name [required] --help Show this message and exit. // Then try completion with your program diff --git a/docs/tutorial/options/help.md b/docs/tutorial/options/help.md index c2a115796f..e72acda473 100644 --- a/docs/tutorial/options/help.md +++ b/docs/tutorial/options/help.md @@ -31,7 +31,7 @@ Test it: ```console $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Say hi to NAME, optionally with a --lastname. @@ -41,7 +41,7 @@ Arguments: NAME [required] Options: - --lastname TEXT Last name of person to greet. [default: ] + --lastname Last name of person to greet. [default: ] --formal / --no-formal Say hi formally. [default: False] --help Show this message and exit. @@ -73,7 +73,7 @@ $ python main.py --help If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [default: None] [required] │ +* name TEXT [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --lastname TEXT Last name of person to greet. │ @@ -119,7 +119,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - --fullname TEXT + --fullname --help Show this message and exit. // Notice there's no [default: Wade Wilson] 🔥 @@ -148,7 +148,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - --fullname TEXT [default: (Deadpoolio the amazing's name)] + --fullname [default: (Deadpoolio the amazing's name)] --help Show this message and exit. // Notice how it shows "(Deadpoolio the amazing's name)" instead of the actual default of "Wade Wilson" diff --git a/docs/tutorial/options/name.md b/docs/tutorial/options/name.md index 621735f7e0..031c3ec431 100644 --- a/docs/tutorial/options/name.md +++ b/docs/tutorial/options/name.md @@ -53,7 +53,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - --name TEXT [required] + --name [required] --help Show this message and exit. // Try it @@ -201,7 +201,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - -n, --name TEXT [required] + -n, --name [required] --help Show this message and exit. // Try the short version @@ -229,7 +229,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - -n TEXT [required] + -n [required] --help Show this message and exit. // Try it @@ -258,7 +258,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - -n, --user-name TEXT [required] + -n, --user-name [required] --help Show this message and exit. // Try it @@ -298,7 +298,7 @@ $ python main.py --help Usage: main.py [OPTIONS] Options: - -n, --name TEXT [required] + -n, --name [required] -f, --formal --help Show this message and exit. diff --git a/docs/tutorial/options/required.md b/docs/tutorial/options/required.md index a702bbaa80..a5852bc1f4 100644 --- a/docs/tutorial/options/required.md +++ b/docs/tutorial/options/required.md @@ -46,7 +46,7 @@ And test it: $ python main.py Camila // We didn't pass the now required --lastname CLI option -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try "main.py --help" for help. Error: Missing option '--lastname'. @@ -59,10 +59,10 @@ Hello Camila Gutiérrez // And if you check the help $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Options: - --lastname TEXT [required] + --lastname [required] --help Show this message and exit. // It now tells you that --lastname is required 🎉 diff --git a/docs/tutorial/options/version.md b/docs/tutorial/options/version.md index 609c3978fc..3a74251cb1 100644 --- a/docs/tutorial/options/version.md +++ b/docs/tutorial/options/version.md @@ -34,7 +34,7 @@ Usage: main.py [OPTIONS] Options: --version - --name TEXT + --name --help Show this message and exit. diff --git a/docs/tutorial/parameter-types/index.md b/docs/tutorial/parameter-types/index.md index ffeb1e88e8..ed52d196e5 100644 --- a/docs/tutorial/parameter-types/index.md +++ b/docs/tutorial/parameter-types/index.md @@ -24,7 +24,7 @@ And here's how it looks like: $ python main.py --help // Notice how --age is an INTEGER and --height-meters is a FLOAT -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Arguments: NAME [required] @@ -47,7 +47,7 @@ NAME is Camila, of type: class 'str' // And if you pass an incorrect type $ python main.py Camila --age 15.3 -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try "main.py --help" for help. Error: Invalid value for '--age': '15.3' is not a valid integer diff --git a/docs/tutorial/typer-app.md b/docs/tutorial/typer-app.md index 29ff2f6812..d28e87ec8e 100644 --- a/docs/tutorial/typer-app.md +++ b/docs/tutorial/typer-app.md @@ -51,10 +51,10 @@ If you run the second example, with the explicit `app`, it works exactly the sam // Without a CLI argument $ python main.py -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Try "main.py --help" for help. -Error: Missing argument 'NAME'. +Error: Missing argument 'name'. // With the NAME CLI argument $ python main.py Camila @@ -64,7 +64,7 @@ Hello Camila // Asking for help $ python main.py --help -Usage: main.py [OPTIONS] NAME +Usage: main.py [OPTIONS] {name} Options: --install-completion Install completion for the current shell. diff --git a/docs/tutorial/typer-command.md b/docs/tutorial/typer-command.md index 5c416a22b6..6758d94f56 100644 --- a/docs/tutorial/typer-command.md +++ b/docs/tutorial/typer-command.md @@ -174,7 +174,7 @@ Usage: typer run [OPTIONS] Say hi to someone, by default to the World. Options: - --name TEXT + --name --help Show this message and exit. $ typer main.py run --name Camila @@ -199,7 +199,7 @@ $ typer my_package.main run --help Usage: typer run [OPTIONS] Options: - --name TEXT + --name --help Show this message and exit. $ typer my_package.main run --name Camila From 4e08df770ab8ca9158647fc33284db5f304c275d Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 13:56:00 +0200 Subject: [PATCH 24/29] fix javascript to escape html --- README.md | 4 ++-- docs/index.md | 4 ++-- docs/js/custom.js | 17 ++++++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ac67ab0e1f..1800951437 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Run the provided Typer app. ╭─ Arguments ───────────────────────────────────────╮ -│ * name [required] | +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -152,7 +152,7 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name [required] | +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ diff --git a/docs/index.md b/docs/index.md index 6a06412850..7f13ebeb16 100644 --- a/docs/index.md +++ b/docs/index.md @@ -102,7 +102,7 @@ Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name} Run the provided Typer app. ╭─ Arguments ───────────────────────────────────────╮ -│ * name [required] | +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ @@ -160,7 +160,7 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────╮ -│ * name [required] | +│ * name [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ diff --git a/docs/js/custom.js b/docs/js/custom.js index 29f2bf8524..0defe2aca7 100644 --- a/docs/js/custom.js +++ b/docs/js/custom.js @@ -1,3 +1,10 @@ +function escapeHtml(text) { + return text + .replace(/&/g, "&") + .replace(//g, ">"); +} + function setupTermynal() { document.querySelectorAll(".use-termynal").forEach(node => { node.style.display = "block"; @@ -36,7 +43,7 @@ function setupTermynal() { // so put an additional one buffer.push(""); } - const bufferValue = buffer.join("
"); + const bufferValue = buffer.map(escapeHtml).join("
"); dataValue["value"] = bufferValue; useLines.push(dataValue); buffer = []; @@ -53,13 +60,13 @@ function setupTermynal() { const value = line.replace(promptLiteralStart, "").trimEnd(); useLines.push({ type: "input", - value: value + value: escapeHtml(value) }); } else if (line.startsWith("// ")) { saveBuffer(); const value = "💬 " + line.replace("// ", "").trimEnd(); useLines.push({ - value: value, + value: escapeHtml(value), class: "termynal-comment", delay: 0 }); @@ -73,8 +80,8 @@ function setupTermynal() { let value = line.slice(promptStart + promptLiteralStart.length); useLines.push({ type: "input", - value: value, - prompt: prompt + value: escapeHtml(value), + prompt: escapeHtml(prompt) }); } else { buffer.push(line); From 780f111a6b4f38d34454effd4aa6375e672885e5 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 14:31:07 +0200 Subject: [PATCH 25/29] final fixes first page of tutorial --- README.md | 2 +- docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1800951437..c6393e8690 100644 --- a/README.md +++ b/README.md @@ -236,8 +236,8 @@ $ python main.py --help │ and exit. │ ╰───────────────────────────────────────────────────╯ ╭─ Commands ────────────────────────────────────────╮ -│ goodbye │ │ hello │ +│ goodbye │ ╰───────────────────────────────────────────────────╯ // When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion diff --git a/docs/index.md b/docs/index.md index 7f13ebeb16..ac13732ffb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -244,8 +244,8 @@ $ python main.py --help │ and exit. │ ╰───────────────────────────────────────────────────╯ ╭─ Commands ────────────────────────────────────────╮ -│ goodbye │ │ hello │ +│ goodbye │ ╰───────────────────────────────────────────────────╯ // When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion From cbf3950fff97d9c3610b469c4ca4645dcbb1a1e9 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 14:51:23 +0200 Subject: [PATCH 26/29] restore all the HTML we do want :-) --- docs/js/custom.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/js/custom.js b/docs/js/custom.js index 0defe2aca7..5f039051fc 100644 --- a/docs/js/custom.js +++ b/docs/js/custom.js @@ -1,10 +1,17 @@ -function escapeHtml(text) { - return text +function escapePlainCliLine(line) { + return line .replace(/&/g, "&") .replace(//g, ">"); } +function prepareTermynalLines(lines, isRichHtml) { + if (isRichHtml) { + return lines.join("
"); + } + return lines.map(escapePlainCliLine).join("
"); +} + function setupTermynal() { document.querySelectorAll(".use-termynal").forEach(node => { node.style.display = "block"; @@ -24,6 +31,11 @@ function setupTermynal() { .forEach(node => { const text = node.textContent; const lines = text.split("\n"); + // If it's a type in brackets like , it doesn't have a space + // and won't have a closing tag, while Rich HTML tags do. + const hasOpeningTagWithSpace = /<[a-zA-Z0-9]+\s/.test(text); + const hasClosingTag = /<\/[a-zA-Z0-9]+>/.test(text); + const isRichHtml = hasOpeningTagWithSpace || hasClosingTag; const useLines = []; let buffer = []; function saveBuffer() { @@ -43,7 +55,7 @@ function setupTermynal() { // so put an additional one buffer.push(""); } - const bufferValue = buffer.map(escapeHtml).join("
"); + const bufferValue = prepareTermynalLines(buffer, isRichHtml); dataValue["value"] = bufferValue; useLines.push(dataValue); buffer = []; @@ -60,13 +72,13 @@ function setupTermynal() { const value = line.replace(promptLiteralStart, "").trimEnd(); useLines.push({ type: "input", - value: escapeHtml(value) + value: value }); } else if (line.startsWith("// ")) { saveBuffer(); const value = "💬 " + line.replace("// ", "").trimEnd(); useLines.push({ - value: escapeHtml(value), + value: value, class: "termynal-comment", delay: 0 }); @@ -80,8 +92,8 @@ function setupTermynal() { let value = line.slice(promptStart + promptLiteralStart.length); useLines.push({ type: "input", - value: escapeHtml(value), - prompt: escapeHtml(prompt) + value: value, + prompt: prompt }); } else { buffer.push(line); From 33eb26971b85bdb9506f26b5c30451dd7cc1c575 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 15:56:38 +0200 Subject: [PATCH 27/29] many more docs fixes (still WIP) --- README.md | 4 +- docs/index.md | 4 +- docs/tutorial/arguments/default.md | 8 +-- docs/tutorial/arguments/envvar.md | 12 ++--- docs/tutorial/arguments/help.md | 44 +++++++-------- docs/tutorial/arguments/optional.md | 8 +-- docs/tutorial/commands/arguments.md | 2 +- docs/tutorial/commands/callback.md | 4 +- docs/tutorial/commands/help.md | 54 +++++++++---------- docs/tutorial/commands/one-or-multiple.md | 2 +- docs/tutorial/first-steps.md | 41 +++++++------- .../arguments-with-multiple-values.md | 4 +- .../options-with-multiple-values.md | 4 +- docs/tutorial/one-file-per-command.md | 4 +- docs/tutorial/options/help.md | 12 ++--- docs/tutorial/options/prompt.md | 4 +- docs/tutorial/options/required.md | 2 +- docs/tutorial/parameter-types/index.md | 6 +-- docs/tutorial/typer-app.md | 2 +- docs/tutorial/typer-command.md | 18 +++---- typer/.agents/skills/typer/SKILL.md | 4 +- 21 files changed, 120 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index c6393e8690..6fb698d454 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Run the provided Typer app. │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯ -// Now pass the NAME argument +// Now pass the 'name' argument $ typer main.py run Camila Hello Camila @@ -158,7 +158,7 @@ Usage: main.py [OPTIONS] {name} │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯ -// Now pass the NAME argument +// Now pass the 'name' argument $ python main.py Camila Hello Camila diff --git a/docs/index.md b/docs/index.md index ac13732ffb..6312199f3d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -108,7 +108,7 @@ Run the provided Typer app. │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯ -// Now pass the NAME argument +// Now pass the 'name' argument $ typer main.py run Camila Hello Camila @@ -166,7 +166,7 @@ Usage: main.py [OPTIONS] {name} │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯ -// Now pass the NAME argument +// Now pass the 'name' argument $ python main.py Camila Hello Camila diff --git a/docs/tutorial/arguments/default.md b/docs/tutorial/arguments/default.md index c03e6931e8..461fe9ac25 100644 --- a/docs/tutorial/arguments/default.md +++ b/docs/tutorial/arguments/default.md @@ -27,10 +27,10 @@ Check it: $ python main.py --help // Notice the [default: Wade Wilson] ✨ -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] [default: Wade Wilson] + [name] [default: Wade Wilson] Options: --help Show this message and exit. @@ -72,10 +72,10 @@ Check it: // Check the help $ python main.py --help -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] [default: (dynamic)] + [name] [default: (dynamic)] Options: --help Show this message and exit. diff --git a/docs/tutorial/arguments/envvar.md b/docs/tutorial/arguments/envvar.md index 53d04c9862..e2709ee911 100644 --- a/docs/tutorial/arguments/envvar.md +++ b/docs/tutorial/arguments/envvar.md @@ -20,10 +20,10 @@ In this case, the *CLI argument* `name` will have a default value of `"World"`, // Check the help $ python main.py --help -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] [env var: AWESOME_NAME;default: World] + [name] [env var: AWESOME_NAME;default: World] Options: --help Show this message and exit. @@ -65,10 +65,10 @@ Check it: // Check the help $ python main.py --help -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] [env var: AWESOME_NAME, GOD_NAME;default: World] + [name] [env var: AWESOME_NAME, GOD_NAME;default: World] Options: --help Show this message and exit. @@ -101,10 +101,10 @@ Check it: $ python main.py --help // It won't show the env var -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] [default: World] + [name] [default: World] Options: --help Show this message and exit. diff --git a/docs/tutorial/arguments/help.md b/docs/tutorial/arguments/help.md index 0882e84747..d2c62af64a 100644 --- a/docs/tutorial/arguments/help.md +++ b/docs/tutorial/arguments/help.md @@ -25,7 +25,7 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} Arguments: - NAME The name of the user to greet [required] + name The name of the user to greet [required] Options: --help Show this message and exit. @@ -49,10 +49,10 @@ $ python main.py --help // Notice that we have the help text from the docstring and also the Arguments 📝 Usage: main.py [OPTIONS] {name} - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. Arguments: - NAME The name of the user to greet [required] + name The name of the user to greet [required] Options: --help Show this message and exit. @@ -74,12 +74,12 @@ It will show that default value in the help text: $ python main.py --help // Notice the [default: World] 🔍 -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. Arguments: - [NAME] Who to greet [default: World] + [name] Who to greet [default: World] Options: --help Show this message and exit. @@ -99,12 +99,12 @@ And then it won't show the default value: $ python main.py --help // Notice the there's no [default: World] now 🔥 -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. Arguments: - [NAME] Who to greet + [name] Who to greet Options: --help Show this message and exit. @@ -125,10 +125,10 @@ And it will be used in the help text: ```console $ python main.py --help -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] Who to greet [default: (Deadpoolio the amazing's name)] + [name] Who to greet [default: (Deadpoolio the amazing's name)] Options: @@ -143,7 +143,7 @@ Options: You can also customize the text used in the generated help text to represent a *CLI argument*. -By default, it will be the same name you declared, in uppercase letters. +By default, it will be the same name you declared, with casing preserved. So, if you declare it as: @@ -154,16 +154,16 @@ name: str It will be shown as: ``` -NAME +name ``` But you can customize it with the `metavar` parameter for `typer.Argument()`. -For example, let's say you don't want to have the default of `NAME`, you want to have `username`, in lowercase, and you really want ✨ emojis ✨ everywhere: +For example, let's say you don't want to have the default of `name`, you want to have `username`, and you really want ✨ emojis ✨ everywhere: {* docs_src/arguments/help/tutorial006_an_py310.py hl[9] *} -Now the generated help text will have `✨username✨` instead of `NAME`: +Now the generated help text will have `✨username✨` instead of `name`:
@@ -198,16 +198,16 @@ And next you will see other panels for the *CLI arguments* that have a custom pa ```console $ python main.py --help - Usage: main.py [OPTIONS] {name} [LASTNAME] [age] + Usage: main.py [OPTIONS] {name} [lastname] [age] - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT Who to greet [default: None] [required] │ +* name str Who to greet [default: None] [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Secondary Arguments ─────────────────────────────────────────────╮ -│ lastname [LASTNAME] The last name │ -│ age [AGE] The user's age │ +│ lastname [lastname] The last name │ +│ age [age] The user's age │ ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --help Show this message and exit. │ @@ -240,9 +240,9 @@ Check it: $ python main.py --help // Notice there's no Arguments section at all 🔥 -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. Options: --help Show this message and exit. diff --git a/docs/tutorial/arguments/optional.md b/docs/tutorial/arguments/optional.md index 62c2d7e311..2d0681a338 100644 --- a/docs/tutorial/arguments/optional.md +++ b/docs/tutorial/arguments/optional.md @@ -132,10 +132,10 @@ Check the help: // First check the help $ python main.py --help -Usage: main.py [OPTIONS] [NAME] +Usage: main.py [OPTIONS] [name] Arguments: - [NAME] + [name] Options: --help Show this message and exit. @@ -145,9 +145,9 @@ Options: /// tip -Notice that `NAME` is still a *CLI argument*, it's shown up there in the "`Usage: main.py` ...". +Notice that `name` is still a *CLI argument*, it's shown up there in the "`Usage: main.py` ...". -Also notice that now `[NAME]` has brackets ("`[`" and "`]`") around (before it was just `NAME`) to denote that it's **optional**, not **required**. +Also notice that now `[name]` has rectangular brackets ("`[`" and "`]`") around it to denote that it's **optional**, not **required**. /// diff --git a/docs/tutorial/commands/arguments.md b/docs/tutorial/commands/arguments.md index a20fd82d51..5582e348a6 100644 --- a/docs/tutorial/commands/arguments.md +++ b/docs/tutorial/commands/arguments.md @@ -10,7 +10,7 @@ The same way as with a CLI application with a single command, subcommands (or ju // Check the help for create $ python main.py create --help -Usage: main.py create [OPTIONS] USERNAME +Usage: main.py create [OPTIONS] username Options: --help Show this message and exit. diff --git a/docs/tutorial/commands/callback.md b/docs/tutorial/commands/callback.md index c3db29887a..e7acb36846 100644 --- a/docs/tutorial/commands/callback.md +++ b/docs/tutorial/commands/callback.md @@ -67,7 +67,7 @@ Just created a user // Notice that --verbose belongs to the callback, it has to go before create or delete ⛔️ $ python main.py create --verbose Camila -Usage: main.py create [OPTIONS] USERNAME +Usage: main.py create [OPTIONS] username Try "main.py create --help" for help. Error: No such option: --verbose @@ -142,7 +142,7 @@ Usage: main.py [OPTIONS] COMMAND [ARGS]... Use it with the create command. - A new user with the given NAME will be created. + A new user with the given 'name' will be created. Options: --install-completion Install completion for the current shell. diff --git a/docs/tutorial/commands/help.md b/docs/tutorial/commands/help.md index 97492d479a..5638c282f9 100644 --- a/docs/tutorial/commands/help.md +++ b/docs/tutorial/commands/help.md @@ -24,8 +24,8 @@ Options: --help Show this message and exit. Commands: - create Create a new user with USERNAME. - delete Delete a user with USERNAME. + create Create a new user with 'username'. + delete Delete a user with 'username'. delete-all Delete ALL users in the database. init Initialize the users database. @@ -34,9 +34,9 @@ Commands: // Check the help for create $ python main.py create --help -Usage: main.py create [OPTIONS] USERNAME +Usage: main.py create [OPTIONS] {username} - Create a new user with USERNAME. + Create a new user with 'username'. Options: --help Show this message and exit. @@ -44,9 +44,9 @@ Options: // Check the help for delete $ python main.py delete --help -Usage: main.py delete [OPTIONS] USERNAME +Usage: main.py delete [OPTIONS] {username} - Delete a user with USERNAME. + Delete a user with 'username'. If --force is not used, will ask for confirmation. @@ -112,10 +112,10 @@ Options: --help Show this message and exit. Commands: - create Create a new user with USERNAME. - delete Delete a user with USERNAME. + create Create a new user with 'username'. + delete Delete a user with 'username'. -// It uses "Create a new user with USERNAME." instead of "Some internal utility function to create." +// It uses "Create a new user with 'username'." instead of "Some internal utility function to create." ```
@@ -160,14 +160,14 @@ And if you check the `--help` for the deprecated command (in this example, the c ```console $ python main.py delete --help - Usage: main.py delete [OPTIONS] USERNAME + Usage: main.py delete [OPTIONS] {username} (deprecated) Delete a user. This is deprecated and will stop being supported soon. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT [required] │ +* username [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --help Show this message and exit. │ @@ -232,13 +232,13 @@ Check the help for the `create` command: ```console $ python main.py create --help - Usage: main.py create [OPTIONS] USERNAME + Usage: main.py create [OPTIONS] {username} Create a new shiny user. ✨ This requires a username. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to be created │ +* username The username to be created[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -255,12 +255,12 @@ And check the help for the `delete` command: ```console $ python main.py delete --help - Usage: main.py delete [OPTIONS] USERNAME + Usage: main.py delete [OPTIONS] {username} - Delete a user with USERNAME. + Delete a user with 'username'. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to be deleted │ +* username The username to be deleted[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -289,7 +289,7 @@ Check the help for the `create` command: ```console $ python main.py create --help - Usage: main.py create [OPTIONS] USERNAME + Usage: main.py create [OPTIONS] {username} Create a new shiny user. ✨ @@ -300,7 +300,7 @@ $ python main.py create --help Learn more at the Typer docs website ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to be created │ +* username The username to be created[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -317,12 +317,12 @@ And the same for the `delete` command: ```console $ python main.py delete --help - Usage: main.py delete [OPTIONS] USERNAME + Usage: main.py delete [OPTIONS] {username} - Delete a user with USERNAME. + Delete a user with 'username'. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to be deleted │ +* username The username to be deleted[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -407,16 +407,16 @@ You can check the `--help` option for the command `create`: ```console $ python main.py create --help - Usage: main.py create [OPTIONS] USERNAME [LASTNAME] + Usage: main.py create [OPTIONS] {username} [lastname] Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT The username to create │ +* username The username to create │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Secondary Arguments ─────────────────────────────────────────────╮ -│ lastname [LASTNAME] The last name of the new user │ +│ lastname [lastname] The last name of the new user │ ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --force --no-force Force the creation of the user │ @@ -425,7 +425,7 @@ $ python main.py create --help ╰───────────────────────────────────────────────────────────────────╯ ╭─ Additional Data ─────────────────────────────────────────────────╮ --age INTEGER The age of the new user │ ---favorite-color TEXT The favorite color of the new │ +--favorite-color The favorite color of the new │ │ user │ ╰───────────────────────────────────────────────────────────────────╯ ``` @@ -476,12 +476,12 @@ And when you check the `--help` option it will look like: ```console $ python main.py --help - Usage: main.py [OPTIONS] USERNAME + Usage: main.py [OPTIONS] {username} Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username TEXT [required] │ +* username [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --install-completion Install completion for the current │ diff --git a/docs/tutorial/commands/one-or-multiple.md b/docs/tutorial/commands/one-or-multiple.md index 6af9084fa5..5a1450644e 100644 --- a/docs/tutorial/commands/one-or-multiple.md +++ b/docs/tutorial/commands/one-or-multiple.md @@ -17,7 +17,7 @@ Try "main.py --help" for help. Error: Missing argument 'name'. -// With the NAME CLI argument +// With the 'name' CLI argument $ python main.py Camila Hello Camila diff --git a/docs/tutorial/first-steps.md b/docs/tutorial/first-steps.md index ddbc99c7bf..a7cc828fd3 100644 --- a/docs/tutorial/first-steps.md +++ b/docs/tutorial/first-steps.md @@ -76,7 +76,7 @@ $ python main.py Missing argument 'name'. ╰───────────────────────────────────────────────────╯ -// Now pass that NAME CLI argument +// Now pass that 'name' CLI argument $ python main.py Camila Hello Camila @@ -111,19 +111,16 @@ So, extend that to have 2 arguments, `name` and `lastname`: // Check the main --help $ python main.py --help -Usage: main.py [OPTIONS] {name} -Try 'main.py --help' for help. -╭─ Error ───────────────────────────────────────────╮ - Missing argument 'name'. -╰───────────────────────────────────────────────────╯ - -typer on  richify [»!?] via 🐍 v3.7.5 (env3.7) - python main.py -Usage: main.py [OPTIONS] {name} {lastname} -Try 'main.py --help' for help. -╭─ Error ───────────────────────────────────────────╮ - Missing argument 'name'. -╰───────────────────────────────────────────────────╯ + Usage: main.py [OPTIONS] {name} {lastname} + +╭─ Arguments ─────────────────────────────────────────────────────╮ +* name [required] │ +* lastname [required] │ +╰─────────────────────────────────────────────────────────────────╯ +╭─ Options ───────────────────────────────────────────────────────╮ +--help Show this message and │ +│ exit. │ +╰─────────────────────────────────────────────────────────────────╯ // There are now 2 CLI arguments, name and lastname @@ -133,7 +130,7 @@ $ python main.py Camila Usage: main.py [OPTIONS] {name} {lastname} Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ - Missing argument 'lastname'. + Missing argument 'lastname'. ╰───────────────────────────────────────────────────╯ // These 2 arguments are required, so, pass both: @@ -241,8 +238,8 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} {lastname} ╭─ Arguments ─────────────────────────────────────────────────────╮ -* name TEXT [required] │ -* lastname TEXT [required] │ +* name [required] │ +* lastname [required]╰─────────────────────────────────────────────────────────────────╯ ╭─ Options ───────────────────────────────────────────────────────╮ --formal --no-formal [default: no-formal] │ @@ -301,10 +298,10 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [required] │ +* name [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname TEXT │ +--lastname --formal --no-formal [default: no-formal] │ --help Show this message │ │ and exit. │ @@ -371,14 +368,14 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [required] │ +* name [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname TEXT │ +--lastname --formal --no-formal [default: no-formal] │ --help Show this message │ │ and exit. │ diff --git a/docs/tutorial/multiple-values/arguments-with-multiple-values.md b/docs/tutorial/multiple-values/arguments-with-multiple-values.md index 2446974667..8b2cdf8775 100644 --- a/docs/tutorial/multiple-values/arguments-with-multiple-values.md +++ b/docs/tutorial/multiple-values/arguments-with-multiple-values.md @@ -47,10 +47,10 @@ Check it: // Check the help $ python main.py --help -Usage: main.py [OPTIONS] [NAMES]... +Usage: main.py [OPTIONS] [names]... Arguments: - [NAMES]... Select 3 characters to play with [default: Harry, Hermione, Ron] + [names]... Select 3 characters to play with [default: Harry, Hermione, Ron] Options: --help Show this message and exit. diff --git a/docs/tutorial/multiple-values/options-with-multiple-values.md b/docs/tutorial/multiple-values/options-with-multiple-values.md index 75b253c4ca..25ecce8176 100644 --- a/docs/tutorial/multiple-values/options-with-multiple-values.md +++ b/docs/tutorial/multiple-values/options-with-multiple-values.md @@ -58,11 +58,11 @@ Now let's see how this works in the terminal: // check the help $ python main.py --help -// Notice the <TEXT INTEGER BOOLEAN> +// Notice the <str int boolean> Usage: main.py [OPTIONS] Options: - --user <TEXT INTEGER BOOLEAN>... + --user <str int boolean>... --help Show this message and exit. // Now try it diff --git a/docs/tutorial/one-file-per-command.md b/docs/tutorial/one-file-per-command.md index 82fc744d69..d9ac0c9b51 100644 --- a/docs/tutorial/one-file-per-command.md +++ b/docs/tutorial/one-file-per-command.md @@ -7,8 +7,8 @@ This tutorial will show you how to use `add_typer` to create sub commands and or We will create a simple CLI with the following commands: - `version` -- `users add NAME` -- `users delete NAME` +- `users add 'name'` +- `users delete 'name'` ## CLI structure diff --git a/docs/tutorial/options/help.md b/docs/tutorial/options/help.md index e72acda473..f5f9ad6ce6 100644 --- a/docs/tutorial/options/help.md +++ b/docs/tutorial/options/help.md @@ -33,12 +33,12 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. Arguments: - NAME [required] + name [required] Options: --lastname Last name of person to greet. [default: ] @@ -67,16 +67,16 @@ And below you will see other panels for the *CLI options* that have a custom pan ```console $ python main.py --help - Usage: main.py [OPTIONS] NAME + Usage: main.py [OPTIONS] name - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name TEXT [required] │ +* name [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname TEXT Last name of person to greet. │ +--lastname Last name of person to greet. │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────────────────────╯ ╭─ Customization and Utils ─────────────────────────────────────────╮ diff --git a/docs/tutorial/options/prompt.md b/docs/tutorial/options/prompt.md index 6919e17980..09156f4cb5 100644 --- a/docs/tutorial/options/prompt.md +++ b/docs/tutorial/options/prompt.md @@ -9,7 +9,7 @@ And then your program will ask the user for it in the terminal:
```console -// Call it with the NAME CLI argument +// Call it with the 'name' CLI argument $ python main.py Camila // It asks for the missing CLI option --lastname @@ -31,7 +31,7 @@ And then your program will ask for it using with your custom prompt:
```console -// Call it with the NAME CLI argument +// Call it with the 'name' CLI argument $ python main.py Camila // It uses the custom prompt diff --git a/docs/tutorial/options/required.md b/docs/tutorial/options/required.md index a5852bc1f4..ec4c7cc542 100644 --- a/docs/tutorial/options/required.md +++ b/docs/tutorial/options/required.md @@ -42,7 +42,7 @@ And test it:
```console -// Pass the NAME CLI argument +// Pass the 'name' CLI argument $ python main.py Camila // We didn't pass the now required --lastname CLI option diff --git a/docs/tutorial/parameter-types/index.md b/docs/tutorial/parameter-types/index.md index ed52d196e5..7984c531db 100644 --- a/docs/tutorial/parameter-types/index.md +++ b/docs/tutorial/parameter-types/index.md @@ -10,7 +10,7 @@ For example: {* docs_src/parameter_types/index/tutorial001_py310.py hl[7] *} -In this example, the value received for the *CLI argument* `NAME` will be treated as `str`. +In this example, the value received for the *CLI argument* `name` will be treated as `str`. The value for the *CLI option* `--age` will be converted to an `int` and `--height-meters` will be converted to a `float`. @@ -27,7 +27,7 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} Arguments: - NAME [required] + name [required] Options: --age INTEGER [default: 20] @@ -39,7 +39,7 @@ Options: $ python main.py Camila --age 15 --height-meters 1.70 --female // All the data has the correct Python type -NAME is Camila, of type: class 'str' +name is Camila, of type: class 'str' --age is 15, of type: class 'int' --height-meters is 1.7, of type: class 'float' --female is True, of type: class 'bool' diff --git a/docs/tutorial/typer-app.md b/docs/tutorial/typer-app.md index d28e87ec8e..92dca688ac 100644 --- a/docs/tutorial/typer-app.md +++ b/docs/tutorial/typer-app.md @@ -56,7 +56,7 @@ Try "main.py --help" for help. Error: Missing argument 'name'. -// With the NAME CLI argument +// With the 'name' CLI argument $ python main.py Camila Hello Camila diff --git a/docs/tutorial/typer-command.md b/docs/tutorial/typer-command.md index 6758d94f56..998905571e 100644 --- a/docs/tutorial/typer-command.md +++ b/docs/tutorial/typer-command.md @@ -265,9 +265,9 @@ $ python -m typer some_script.py utils docs **Options**: -* `--name TEXT`: The name of the CLI program to use in docs. -* `--output FILE`: An output file to write docs to, like README.md. -* `--title TEXT`: A title to use in the docs, by default the name of the command. +* `--name `: The name of the CLI program to use in docs. +* `--output `: An output file to write docs to, like README.md. +* `--title `: A title to use in the docs, by default the name of the command. For example: @@ -305,19 +305,19 @@ $ awesome-cli [OPTIONS] COMMAND [ARGS]... **Commands**: -* `create`: Create a new user with USERNAME. -* `delete`: Delete a user with USERNAME. +* `create`: Create a new user with 'username'. +* `delete`: Delete a user with 'username'. * `delete-all`: Delete ALL users in the database. * `init`: Initialize the users database. ## `awesome-cli create` -Create a new user with USERNAME. +Create a new user with 'username'. **Usage**: ```console -$ awesome-cli create [OPTIONS] USERNAME +$ awesome-cli create [OPTIONS] {username} ``` **Options**: @@ -326,14 +326,14 @@ $ awesome-cli create [OPTIONS] USERNAME ## `awesome-cli delete` -Delete a user with USERNAME. +Delete a user with 'username'. If --force is not used, will ask for confirmation. **Usage**: ```console -$ awesome-cli delete [OPTIONS] USERNAME +$ awesome-cli delete [OPTIONS] {username} ``` **Options**: diff --git a/typer/.agents/skills/typer/SKILL.md b/typer/.agents/skills/typer/SKILL.md index 60cf47a391..1ce63958cb 100644 --- a/typer/.agents/skills/typer/SKILL.md +++ b/typer/.agents/skills/typer/SKILL.md @@ -240,7 +240,7 @@ def create( print(f"Creating user: {username}") -@app.command(help="[bold red]Delete[/bold red] a user with [italic]USERNAME[/italic].") +@app.command(help="[bold red]Delete[/bold red] a user with [italic]username[/italic].") def delete( username: Annotated[ str, typer.Argument(help="The username to be [red]deleted[/red]") @@ -269,7 +269,7 @@ import typer app = typer.Typer(rich_markup_mode="markdown") -@app.command(help="**Delete** a user with *USERNAME*.") +@app.command(help="**Delete** a user with *username*.") def delete( username: Annotated[str, typer.Argument(help="The username to be **deleted** :boom:")] ): From 2c3187408d6362e0b299231f3759f0140767fde1 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 16:37:24 +0200 Subject: [PATCH 28/29] fix types vs HTML tags, continued --- docs/tutorial/commands/help.md | 16 ++++++++-------- docs/tutorial/first-steps.md | 16 ++++++++-------- docs/tutorial/options/help.md | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/tutorial/commands/help.md b/docs/tutorial/commands/help.md index 5638c282f9..cf29394a9c 100644 --- a/docs/tutorial/commands/help.md +++ b/docs/tutorial/commands/help.md @@ -167,7 +167,7 @@ $ python main.py delete --help This is deprecated and will stop being supported soon. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username [required] │ +* username <str> [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --help Show this message and exit. │ @@ -238,7 +238,7 @@ $ python main.py create --help This requires a username. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username The username to be created │ +* username <str> The username to be created[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -260,7 +260,7 @@ $ python main.py delete --help Delete a user with 'username'. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username The username to be deleted │ +* username <str> The username to be deleted[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -300,7 +300,7 @@ $ python main.py create --help Learn more at the Typer docs website ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username The username to be created │ +* username <str> The username to be created[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -322,7 +322,7 @@ $ python main.py delete --help Delete a user with 'username'. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username The username to be deleted │ +* username <str> The username to be deleted[required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ @@ -412,7 +412,7 @@ $ python main.py create --help Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username The username to create │ +* username <str> The username to create │ [required] ╰───────────────────────────────────────────────────────────────────╯ ╭─ Secondary Arguments ─────────────────────────────────────────────╮ @@ -425,7 +425,7 @@ $ python main.py create --help ╰───────────────────────────────────────────────────────────────────╯ ╭─ Additional Data ─────────────────────────────────────────────────╮ --age INTEGER The age of the new user │ ---favorite-color The favorite color of the new │ +--favorite-color <str> The favorite color of the new │ │ user │ ╰───────────────────────────────────────────────────────────────────╯ ``` @@ -481,7 +481,7 @@ $ python main.py --help Create a new user. ✨ ╭─ Arguments ───────────────────────────────────────────────────────╮ -* username [required] │ +* username <str> [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ --install-completion Install completion for the current │ diff --git a/docs/tutorial/first-steps.md b/docs/tutorial/first-steps.md index a7cc828fd3..c7b088157b 100644 --- a/docs/tutorial/first-steps.md +++ b/docs/tutorial/first-steps.md @@ -114,8 +114,8 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} {lastname} ╭─ Arguments ─────────────────────────────────────────────────────╮ -* name [required] │ -* lastname [required] │ +* name <str> [required] │ +* lastname <str> [required]╰─────────────────────────────────────────────────────────────────╯ ╭─ Options ───────────────────────────────────────────────────────╮ --help Show this message and │ @@ -238,8 +238,8 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} {lastname} ╭─ Arguments ─────────────────────────────────────────────────────╮ -* name [required] │ -* lastname [required] │ +* name <str> [required] │ +* lastname <str> [required]╰─────────────────────────────────────────────────────────────────╯ ╭─ Options ───────────────────────────────────────────────────────╮ --formal --no-formal [default: no-formal] │ @@ -298,10 +298,10 @@ $ python main.py --help Usage: main.py [OPTIONS] {name} ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name [required] │ +* name <str> [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname │ +--lastname <str>--formal --no-formal [default: no-formal] │ --help Show this message │ │ and exit. │ @@ -372,10 +372,10 @@ $ python main.py --help If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name [required] │ +* name <str> [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname │ +--lastname <str>--formal --no-formal [default: no-formal] │ --help Show this message │ │ and exit. │ diff --git a/docs/tutorial/options/help.md b/docs/tutorial/options/help.md index f5f9ad6ce6..f9257c12b1 100644 --- a/docs/tutorial/options/help.md +++ b/docs/tutorial/options/help.md @@ -73,10 +73,10 @@ $ python main.py --help If --formal is used, say hi very formally. ╭─ Arguments ───────────────────────────────────────────────────────╮ -* name [required] │ +* name <str> [required]╰───────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────╮ ---lastname Last name of person to greet. │ +--lastname <str> Last name of person to greet. │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────────────────────╯ ╭─ Customization and Utils ─────────────────────────────────────────╮ From df30ebc5cc9be09b2e4f402caf35afc8a2a24182 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 10 Jul 2026 16:48:01 +0200 Subject: [PATCH 29/29] update docstrings to be consistent --- docs_src/arguments/help/tutorial002_an_py310.py | 2 +- docs_src/arguments/help/tutorial002_py310.py | 2 +- docs_src/arguments/help/tutorial003_an_py310.py | 2 +- docs_src/arguments/help/tutorial003_py310.py | 2 +- docs_src/arguments/help/tutorial004_an_py310.py | 2 +- docs_src/arguments/help/tutorial004_py310.py | 2 +- docs_src/arguments/help/tutorial007_an_py310.py | 2 +- docs_src/arguments/help/tutorial007_py310.py | 2 +- docs_src/arguments/help/tutorial008_an_py310.py | 2 +- docs_src/arguments/help/tutorial008_py310.py | 2 +- docs_src/first_steps/tutorial006_py310.py | 2 +- docs_src/options/help/tutorial001_an_py310.py | 2 +- docs_src/options/help/tutorial001_py310.py | 2 +- docs_src/options/help/tutorial002_an_py310.py | 2 +- docs_src/options/help/tutorial002_py310.py | 2 +- .../test_arguments/test_help/test_tutorial002.py | 2 +- .../test_arguments/test_help/test_tutorial003.py | 2 +- .../test_arguments/test_help/test_tutorial004.py | 2 +- .../test_arguments/test_help/test_tutorial007.py | 2 +- .../test_arguments/test_help/test_tutorial008.py | 4 ++-- tests/test_tutorial/test_first_steps/test_tutorial006.py | 2 +- .../test_tutorial/test_options/test_help/test_tutorial001.py | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs_src/arguments/help/tutorial002_an_py310.py b/docs_src/arguments/help/tutorial002_an_py310.py index 3f029018fb..7fd2b70dbc 100644 --- a/docs_src/arguments/help/tutorial002_an_py310.py +++ b/docs_src/arguments/help/tutorial002_an_py310.py @@ -8,7 +8,7 @@ @app.command() def main(name: Annotated[str, typer.Argument(help="The name of the user to greet")]): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial002_py310.py b/docs_src/arguments/help/tutorial002_py310.py index 27fd086151..11098b1085 100644 --- a/docs_src/arguments/help/tutorial002_py310.py +++ b/docs_src/arguments/help/tutorial002_py310.py @@ -6,7 +6,7 @@ @app.command() def main(name: str = typer.Argument(..., help="The name of the user to greet")): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial003_an_py310.py b/docs_src/arguments/help/tutorial003_an_py310.py index 6dbc67e04e..ef8441f2f5 100644 --- a/docs_src/arguments/help/tutorial003_an_py310.py +++ b/docs_src/arguments/help/tutorial003_an_py310.py @@ -8,7 +8,7 @@ @app.command() def main(name: Annotated[str, typer.Argument(help="Who to greet")] = "World"): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial003_py310.py b/docs_src/arguments/help/tutorial003_py310.py index 3c6c45061e..183cf318da 100644 --- a/docs_src/arguments/help/tutorial003_py310.py +++ b/docs_src/arguments/help/tutorial003_py310.py @@ -6,7 +6,7 @@ @app.command() def main(name: str = typer.Argument("World", help="Who to greet")): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial004_an_py310.py b/docs_src/arguments/help/tutorial004_an_py310.py index fc4e06f6f1..b926ccadd7 100644 --- a/docs_src/arguments/help/tutorial004_an_py310.py +++ b/docs_src/arguments/help/tutorial004_an_py310.py @@ -12,7 +12,7 @@ def main( ] = "World", ): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial004_py310.py b/docs_src/arguments/help/tutorial004_py310.py index e6afb9c855..ef4bcfee9b 100644 --- a/docs_src/arguments/help/tutorial004_py310.py +++ b/docs_src/arguments/help/tutorial004_py310.py @@ -6,7 +6,7 @@ @app.command() def main(name: str = typer.Argument("World", help="Who to greet", show_default=False)): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial007_an_py310.py b/docs_src/arguments/help/tutorial007_an_py310.py index 3a49db9034..a0585678f8 100644 --- a/docs_src/arguments/help/tutorial007_an_py310.py +++ b/docs_src/arguments/help/tutorial007_an_py310.py @@ -17,7 +17,7 @@ def main( ] = "", ): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial007_py310.py b/docs_src/arguments/help/tutorial007_py310.py index d5437028f5..a6924b2363 100644 --- a/docs_src/arguments/help/tutorial007_py310.py +++ b/docs_src/arguments/help/tutorial007_py310.py @@ -14,7 +14,7 @@ def main( ), ): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial008_an_py310.py b/docs_src/arguments/help/tutorial008_an_py310.py index b1a3ee62c9..0db231345f 100644 --- a/docs_src/arguments/help/tutorial008_an_py310.py +++ b/docs_src/arguments/help/tutorial008_an_py310.py @@ -8,7 +8,7 @@ @app.command() def main(name: Annotated[str, typer.Argument(hidden=True)] = "World"): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/arguments/help/tutorial008_py310.py b/docs_src/arguments/help/tutorial008_py310.py index 59f6b52c32..4a30cd8c44 100644 --- a/docs_src/arguments/help/tutorial008_py310.py +++ b/docs_src/arguments/help/tutorial008_py310.py @@ -6,7 +6,7 @@ @app.command() def main(name: str = typer.Argument("World", hidden=True)): """ - Say hi to NAME very gently, like Dirk. + Say hi to 'name' very gently, like Dirk. """ print(f"Hello {name}") diff --git a/docs_src/first_steps/tutorial006_py310.py b/docs_src/first_steps/tutorial006_py310.py index 102ce8d70e..4970833ded 100644 --- a/docs_src/first_steps/tutorial006_py310.py +++ b/docs_src/first_steps/tutorial006_py310.py @@ -3,7 +3,7 @@ def main(name: str, lastname: str = "", formal: bool = False): """ - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. """ diff --git a/docs_src/options/help/tutorial001_an_py310.py b/docs_src/options/help/tutorial001_an_py310.py index 9ae2e34434..0a7f9d0429 100644 --- a/docs_src/options/help/tutorial001_an_py310.py +++ b/docs_src/options/help/tutorial001_an_py310.py @@ -12,7 +12,7 @@ def main( formal: Annotated[bool, typer.Option(help="Say hi formally.")] = False, ): """ - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. """ diff --git a/docs_src/options/help/tutorial001_py310.py b/docs_src/options/help/tutorial001_py310.py index 617d946d55..1b4c0f1178 100644 --- a/docs_src/options/help/tutorial001_py310.py +++ b/docs_src/options/help/tutorial001_py310.py @@ -10,7 +10,7 @@ def main( formal: bool = typer.Option(False, help="Say hi formally."), ): """ - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. """ diff --git a/docs_src/options/help/tutorial002_an_py310.py b/docs_src/options/help/tutorial002_an_py310.py index 104d8b200e..31c5857c15 100644 --- a/docs_src/options/help/tutorial002_an_py310.py +++ b/docs_src/options/help/tutorial002_an_py310.py @@ -23,7 +23,7 @@ def main( ] = False, ): """ - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. """ diff --git a/docs_src/options/help/tutorial002_py310.py b/docs_src/options/help/tutorial002_py310.py index d811348249..43d54ef812 100644 --- a/docs_src/options/help/tutorial002_py310.py +++ b/docs_src/options/help/tutorial002_py310.py @@ -15,7 +15,7 @@ def main( ), ): """ - Say hi to NAME, optionally with a --lastname. + Say hi to 'name', optionally with a --lastname. If --formal is used, say hi very formally. """ diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py index f3fd10a9d1..af2181d183 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial002.py @@ -26,7 +26,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] {name}" in result.output - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" in result.output assert "{name}" in result.output assert "The name of the user to greet" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py index dc7ef0234c..c24804b917 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial003.py @@ -26,7 +26,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [name]" in result.output - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" in result.output assert "[name]" in result.output assert "Who to greet" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py index 451e3272ad..a885e3f868 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial004.py @@ -26,7 +26,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [name]" in result.output - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" in result.output assert "[name]" in result.output assert "Who to greet" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py index a51ca0a3e8..0337e933e6 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial007.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" in result.output assert "Secondary Arguments" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py index 004dbbcfe1..646342950e 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py @@ -27,7 +27,7 @@ def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [name]" in result.output - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" not in result.output assert "[default: World]" not in result.output @@ -37,7 +37,7 @@ def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [name]" in result.output - assert "Say hi to NAME very gently, like Dirk." in result.output + assert "Say hi to 'name' very gently, like Dirk." in result.output assert "Arguments" not in result.output assert "[default: World]" not in result.output diff --git a/tests/test_tutorial/test_first_steps/test_tutorial006.py b/tests/test_tutorial/test_first_steps/test_tutorial006.py index e2a85d9c0d..38ce63d9d4 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial006.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial006.py @@ -15,7 +15,7 @@ def test_help(): result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 - assert "Say hi to NAME, optionally with a --lastname." in result.output + assert "Say hi to 'name', optionally with a --lastname." in result.output assert "If --formal is used, say hi very formally." in result.output diff --git a/tests/test_tutorial/test_options/test_help/test_tutorial001.py b/tests/test_tutorial/test_options/test_help/test_tutorial001.py index 067bdffe51..62ee6160e6 100644 --- a/tests/test_tutorial/test_options/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_options/test_help/test_tutorial001.py @@ -25,7 +25,7 @@ def get_mod(request: pytest.FixtureRequest) -> ModuleType: def test_help(mod: ModuleType): result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 - assert "Say hi to NAME, optionally with a --lastname." in result.output + assert "Say hi to 'name', optionally with a --lastname." in result.output assert "If --formal is used, say hi very formally." in result.output assert "Last name of person to greet." in result.output assert "Say hi formally." in result.output