From c7c2231d5ac1ab1598319f1187245bd3d4179d0b Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 2 Jun 2026 12:03:35 +0200 Subject: [PATCH 1/4] fix default list --- tests/test_types.py | 6 ++++++ typer/_click/parser.py | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index caeef451aa..d28b781787 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -109,6 +109,12 @@ def test_split_envvar_value(monkeypatch) -> None: assert "Hello Morty!" in result.output +def test_variadic_argument_empty() -> None: + result = runner.invoke(app, ["hello-all"]) + assert result.exit_code == 0 + assert "Hello World!" in result.output + + def test_list_pair() -> None: result = runner.invoke(app, ["split-variadic-and-pair", "a", "b", "c", "x", "y"]) assert result.exit_code == 0 diff --git a/typer/_click/parser.py b/typer/_click/parser.py index 71eb3003cc..3eb5acd632 100644 --- a/typer/_click/parser.py +++ b/typer/_click/parser.py @@ -187,9 +187,9 @@ def process( f"Argument {self.dest!r} takes {self.nargs} values." ) - if self.nargs == -1 and self.obj.envvar is not None and value == (): - # Replace empty tuple with None so that a value from the - # environment may be tried. + if self.nargs == -1 and value == (): + # Replace empty tuple with None so regular default resolution + # (env var, default map, and parameter default) can be tried. value = None state.opts[self.dest] = value # type: ignore From 2792141153468147c18e5ccde02a212ffada71de Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 2 Jun 2026 14:34:59 +0200 Subject: [PATCH 2/4] change to test that fails on master --- tests/test_types.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index d28b781787..ff671b4ad3 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -31,7 +31,15 @@ def hello_no_choices( @app.command() -def hello_all(names: list[str] = typer.Argument(["World"], envvar="NAMES")) -> None: +def hello_all(names: list[str] = typer.Argument(["World"])) -> None: + for name in names: + print(f"Hello {name}!") + + +@app.command() +def hello_all_envvar( + names: list[str] = typer.Argument(["World"], envvar="NAMES"), +) -> None: for name in names: print(f"Hello {name}!") @@ -100,21 +108,25 @@ def test_enum_choice_missing_message() -> None: assert "morty" in result.output +def test_variadic_argument_empty() -> None: + result = runner.invoke(app, ["hello-all"]) + assert result.exit_code == 0 + assert "Hello World!" in result.output + + result = runner.invoke(app, ["hello-all-envvar"]) + assert result.exit_code == 0 + assert "Hello World!" in result.output + + def test_split_envvar_value(monkeypatch) -> None: # This will use split_envvar_value to produce two strings from the envvar monkeypatch.setenv("NAMES", "Rick Morty") - result = runner.invoke(app, ["hello-all"]) + result = runner.invoke(app, ["hello-all-envvar"]) assert result.exit_code == 0 assert "Hello Rick!" in result.output assert "Hello Morty!" in result.output -def test_variadic_argument_empty() -> None: - result = runner.invoke(app, ["hello-all"]) - assert result.exit_code == 0 - assert "Hello World!" in result.output - - def test_list_pair() -> None: result = runner.invoke(app, ["split-variadic-and-pair", "a", "b", "c", "x", "y"]) assert result.exit_code == 0 From bb8ad67db1e73816b17c511f30f41573e41d12ae Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 2 Jun 2026 15:08:40 +0200 Subject: [PATCH 3/4] add a test for Option --- tests/test_types.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index ff671b4ad3..b8d0a8de1f 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -31,7 +31,13 @@ def hello_no_choices( @app.command() -def hello_all(names: list[str] = typer.Argument(["World"])) -> None: +def hello_all_options(name: list[str] = typer.Option(["World"])) -> None: + for n in name: + print(f"Hello {n}!") + + +@app.command() +def hello_all_args(names: list[str] = typer.Argument(["World"])) -> None: for name in names: print(f"Hello {name}!") @@ -108,8 +114,26 @@ def test_enum_choice_missing_message() -> None: assert "morty" in result.output -def test_variadic_argument_empty() -> None: - result = runner.invoke(app, ["hello-all"]) +def test_list() -> None: + result = runner.invoke(app, ["hello-all-options", "--name", "Rick", "--name", "Morty"]) + assert result.exit_code == 0 + assert "Hello World!" not in result.output + assert "Hello Rick!" in result.output + assert "Hello Morty!" in result.output + + result = runner.invoke(app, ["hello-all-args", "Rick", "Morty"]) + assert result.exit_code == 0 + assert "Hello World!" not in result.output + assert "Hello Rick!" in result.output + assert "Hello Morty!" in result.output + + +def test_list_empty() -> None: + result = runner.invoke(app, ["hello-all-args"]) + assert result.exit_code == 0 + assert "Hello World!" in result.output + + result = runner.invoke(app, ["hello-all-options"]) assert result.exit_code == 0 assert "Hello World!" in result.output From 5bec961514de7c5da842c6e3170727022388414b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:09:24 +0000 Subject: [PATCH 4/4] =?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_types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_types.py b/tests/test_types.py index b8d0a8de1f..db6dae08da 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -115,7 +115,9 @@ def test_enum_choice_missing_message() -> None: def test_list() -> None: - result = runner.invoke(app, ["hello-all-options", "--name", "Rick", "--name", "Morty"]) + result = runner.invoke( + app, ["hello-all-options", "--name", "Rick", "--name", "Morty"] + ) assert result.exit_code == 0 assert "Hello World!" not in result.output assert "Hello Rick!" in result.output