Coverage for tests / test_annotated.py: 100%
66 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-09 12:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-09 12:36 +0000
1import sys 1acdhefbg
2from pathlib import Path 1acdhefbg
3from typing import Annotated 1acdhefbg
5import typer 1acdhefbg
6from typer.testing import CliRunner 1acdhefbg
8from .utils import needs_py310 1acdhefbg
10runner = CliRunner() 1acdhefbg
13def test_annotated_argument_with_default(): 1acdhefbg
14 app = typer.Typer() 1acdhefbg
16 @app.command() 1acdhefbg
17 def cmd(val: Annotated[int, typer.Argument()] = 0): 1acdhefbg
18 print(f"hello {val}") 1acdhefbg
20 result = runner.invoke(app) 1acdhefbg
21 assert result.exit_code == 0, result.output 1acdhefbg
22 assert "hello 0" in result.output 1acdhefbg
24 result = runner.invoke(app, ["42"]) 1acdhefbg
25 assert result.exit_code == 0, result.output 1acdhefbg
26 assert "hello 42" in result.output 1acdhefbg
29@needs_py310 1acdhefbg
30def test_annotated_argument_in_string_type_with_default(): 1acdhefbg
31 app = typer.Typer() 1acdefbg
33 @app.command() 1acdefbg
34 def cmd(val: "Annotated[int, typer.Argument()]" = 0): 1acdefbg
35 print(f"hello {val}") 1acdefbg
37 result = runner.invoke(app) 1acdefbg
38 assert result.exit_code == 0, result.output 1acdefbg
39 assert "hello 0" in result.output 1acdefbg
41 result = runner.invoke(app, ["42"]) 1acdefbg
42 assert result.exit_code == 0, result.output 1acdefbg
43 assert "hello 42" in result.output 1acdefbg
46def test_annotated_argument_with_default_factory(): 1acdhefbg
47 app = typer.Typer() 1acdhefbg
49 def make_string(): 1acdhefbg
50 return "I made it" 1acdhefbg
52 @app.command() 1acdhefbg
53 def cmd(val: Annotated[str, typer.Argument(default_factory=make_string)]): 1acdhefbg
54 print(val) 1acdhefbg
56 result = runner.invoke(app) 1acdhefbg
57 assert result.exit_code == 0, result.output 1acdhefbg
58 assert "I made it" in result.output 1acdhefbg
60 result = runner.invoke(app, ["overridden"]) 1acdhefbg
61 assert result.exit_code == 0, result.output 1acdhefbg
62 assert "overridden" in result.output 1acdhefbg
65def test_annotated_option_with_argname_doesnt_mutate_multiple_calls(): 1acdhefbg
66 app = typer.Typer() 1acdhefbg
68 @app.command() 1acdhefbg
69 def cmd(force: Annotated[bool, typer.Option("--force")] = False): 1acdhefbg
70 if force: 1acdhefbg
71 print("Forcing operation") 1acdhefbg
72 else:
73 print("Not forcing") 1acdhefbg
75 result = runner.invoke(app) 1acdhefbg
76 assert result.exit_code == 0, result.output 1acdhefbg
77 assert "Not forcing" in result.output 1acdhefbg
79 result = runner.invoke(app, ["--force"]) 1acdhefbg
80 assert result.exit_code == 0, result.output 1acdhefbg
81 assert "Forcing operation" in result.output 1acdhefbg
84def test_annotated_custom_path(): 1acdhefbg
85 app = typer.Typer() 1acdhefbg
87 class CustomPath(Path): 1acdhefbg
88 # Subclassing Path was not fully supported before 3.12
89 # https://docs.python.org/3.12/whatsnew/3.12.html
90 if sys.version_info < (3, 12): 1acdhefbg
91 _flavour = type(Path())._flavour 1ahb
93 @app.command() 1acdhefbg
94 def custom_parser( 1acdhefbg
95 my_path: Annotated[CustomPath, typer.Argument(parser=CustomPath)],
96 ):
97 assert isinstance(my_path, CustomPath) 1acdhefbg
99 result = runner.invoke(app, "/some/quirky/path/implementation") 1acdhefbg
100 assert result.exit_code == 0 1acdhefbg