From 974307a9d94db4d78c05ab99e52f865d9133648f Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 11:43:00 +0100 Subject: [PATCH 1/6] Improve CLI help handling for `run` command Updated the `run` command so that `--help` is passed to the subcommand if there is one. --- src/dotenv/cli.py | 5 ++++- tests/test_cli.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index c548aa39..d2f3a197 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -156,7 +156,7 @@ def unset(ctx: click.Context, key: Any) -> None: sys.exit(1) -@cli.command(context_settings={"ignore_unknown_options": True}) +@cli.command(context_settings={"ignore_unknown_options": True}, add_help_option=False, no_args_is_help=True) @click.pass_context @click.option( "--override/--no-override", @@ -180,6 +180,9 @@ def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: if not commandline: click.echo("No command given.") sys.exit(1) + if len(commandline) == 1 and commandline[0] in ["-h", "--help"]: + click.echo(ctx.get_help()) + sys.exit(0) run_command(commandline, dotenv_as_dict) diff --git a/tests/test_cli.py b/tests/test_cli.py index 343fdb23..0101a3bd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,6 @@ import os +import subprocess +import sys from pathlib import Path from typing import Optional @@ -249,3 +251,19 @@ def test_run_with_version(cli): assert result.exit_code == 0 assert result.output.strip().endswith(__version__) + + +def test_run_subcommand_with_help_uses_subcommand_help(cli, dotenv_path): + dotenv_path.write_text("a=b") + output = sh.dotenv("--file", dotenv_path, "run", "printenv", "--help") + + assert "dotenv run" not in output + expected_help_output = subprocess.check_output(["printenv", "--help"]).decode("utf-8") + assert output == expected_help_output + + +def test_run_with_just_help_show_help(cli, dotenv_path): + dotenv_path.write_text("a=b") + output = sh.dotenv("--file", dotenv_path, "run", "--help") + + assert "dotenv run" in output From 8157cdd1c48a32a53cfa8f13b58a529b5444a221 Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 11:57:58 +0100 Subject: [PATCH 2/6] updated test_run_without_cmd --- tests/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 0101a3bd..2c6b53c3 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -236,7 +236,7 @@ def test_run_without_cmd(cli): result = cli.invoke(dotenv_cli, ["run"]) assert result.exit_code == 2 - assert "Invalid value for '-f'" in result.output + assert "Usage: cli run" in result.output def test_run_with_invalid_cmd(cli): From 05d38f239ba47befef7d2a48d8100af0a6e97bfe Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 12:01:42 +0100 Subject: [PATCH 3/6] Revert "updated test_run_without_cmd" This reverts commit 8157cdd1c48a32a53cfa8f13b58a529b5444a221. --- tests/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 2c6b53c3..0101a3bd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -236,7 +236,7 @@ def test_run_without_cmd(cli): result = cli.invoke(dotenv_cli, ["run"]) assert result.exit_code == 2 - assert "Usage: cli run" in result.output + assert "Invalid value for '-f'" in result.output def test_run_with_invalid_cmd(cli): From 5d3dd5b3cd9053f51d4af13ca21bc77f68b27e86 Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 12:03:17 +0100 Subject: [PATCH 4/6] revert to previous "No command given." for plain "dotenv run" --- src/dotenv/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index d2f3a197..1d5783be 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -156,7 +156,7 @@ def unset(ctx: click.Context, key: Any) -> None: sys.exit(1) -@cli.command(context_settings={"ignore_unknown_options": True}, add_help_option=False, no_args_is_help=True) +@cli.command(context_settings={"ignore_unknown_options": True}, add_help_option=False) @click.pass_context @click.option( "--override/--no-override", From 0cc49be3d8e5c9b6e301fd80bc7b88f6e1a16a63 Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 12:05:10 +0100 Subject: [PATCH 5/6] removed unused import --- tests/test_cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 0101a3bd..5608addc 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,6 +1,5 @@ import os import subprocess -import sys from pathlib import Path from typing import Optional From a1e48c526bf12aa893943a03795123156e9dea90 Mon Sep 17 00:00:00 2001 From: Bartosz Marcinkowski Date: Mon, 24 Nov 2025 12:07:09 +0100 Subject: [PATCH 6/6] fixed formatting --- tests/test_cli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5608addc..8accfafc 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -257,7 +257,9 @@ def test_run_subcommand_with_help_uses_subcommand_help(cli, dotenv_path): output = sh.dotenv("--file", dotenv_path, "run", "printenv", "--help") assert "dotenv run" not in output - expected_help_output = subprocess.check_output(["printenv", "--help"]).decode("utf-8") + expected_help_output = subprocess.check_output(["printenv", "--help"]).decode( + "utf-8" + ) assert output == expected_help_output