From cf3290deb2bd48e5b8ae7dd1ec901c021ca3fb7a Mon Sep 17 00:00:00 2001 From: theowisear <127741468+theowisear@users.noreply.github.com> Date: Sat, 23 Mar 2024 18:17:14 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20default=20value=20of=20`No?= =?UTF-8?q?ne`=20for=20CLI=20Parameters=20when=20the=20type=20is=20`list?= =?UTF-8?q?=20|=20None`=20and=20the=20default=20value=20is=20`None`=20(#66?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg Co-authored-by: Sebastián Ramírez --- docs/tutorial/multiple-values/multiple-options.md | 3 ++- .../multiple_values/multiple_options/tutorial001.py | 2 +- .../multiple_options/tutorial001_an.py | 2 +- .../test_multiple_options/test_tutorial001.py | 1 + .../test_multiple_options/test_tutorial001_an.py | 1 + typer/main.py | 12 ++++++++---- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/tutorial/multiple-values/multiple-options.md b/docs/tutorial/multiple-values/multiple-options.md index 00754e93b4..d61bee1588 100644 --- a/docs/tutorial/multiple-values/multiple-options.md +++ b/docs/tutorial/multiple-values/multiple-options.md @@ -26,9 +26,10 @@ Check it:
```console +// The default value is 'None' $ python main.py -No provided users +No provided users (raw input = None) Aborted! // Now pass a user diff --git a/docs_src/multiple_values/multiple_options/tutorial001.py b/docs_src/multiple_values/multiple_options/tutorial001.py index 141e9aa1ce..bce2322915 100644 --- a/docs_src/multiple_values/multiple_options/tutorial001.py +++ b/docs_src/multiple_values/multiple_options/tutorial001.py @@ -5,7 +5,7 @@ def main(user: Optional[List[str]] = typer.Option(None)): if not user: - print("No provided users") + print(f"No provided users (raw input = {user})") raise typer.Abort() for u in user: print(f"Processing user: {u}") diff --git a/docs_src/multiple_values/multiple_options/tutorial001_an.py b/docs_src/multiple_values/multiple_options/tutorial001_an.py index 68ad2519ea..3dd19d8f59 100644 --- a/docs_src/multiple_values/multiple_options/tutorial001_an.py +++ b/docs_src/multiple_values/multiple_options/tutorial001_an.py @@ -6,7 +6,7 @@ def main(user: Annotated[Optional[List[str]], typer.Option()] = None): if not user: - print("No provided users") + print(f"No provided users (raw input = {user})") raise typer.Abort() for u in user: print(f"Processing user: {u}") diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py index 3c57bfd33e..4293ed8d3d 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001.py @@ -15,6 +15,7 @@ def test_main(): result = runner.invoke(app) assert result.exit_code != 0 assert "No provided users" in result.output + assert "raw input = None" in result.output assert "Aborted" in result.output diff --git a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py index 0009fd2f05..20ea235307 100644 --- a/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py +++ b/tests/test_tutorial/test_multiple_values/test_multiple_options/test_tutorial001_an.py @@ -15,6 +15,7 @@ def test_main(): result = runner.invoke(app) assert result.exit_code != 0 assert "No provided users" in result.output + assert "raw input = None" in result.output assert "Aborted" in result.output diff --git a/typer/main.py b/typer/main.py index c739a293ae..21683d913a 100644 --- a/typer/main.py +++ b/typer/main.py @@ -631,9 +631,11 @@ def convertor(value: Any) -> Any: def generate_list_convertor( - convertor: Optional[Callable[[Any], Any]] -) -> Callable[[Sequence[Any]], List[Any]]: - def internal_convertor(value: Sequence[Any]) -> List[Any]: + convertor: Optional[Callable[[Any], Any]], default_value: Optional[Any] +) -> Callable[[Sequence[Any]], Optional[List[Any]]]: + def internal_convertor(value: Sequence[Any]) -> Optional[List[Any]]: + if default_value is None and len(value) == 0: + return None return [convertor(v) if convertor else v for v in value] return internal_convertor @@ -852,7 +854,9 @@ def get_click_param( ) convertor = determine_type_convertor(main_type) if is_list: - convertor = generate_list_convertor(convertor) + convertor = generate_list_convertor( + convertor=convertor, default_value=default_value + ) if is_tuple: convertor = generate_tuple_convertor(main_type.__args__) if isinstance(parameter_info, OptionInfo):