From 717c81994782f6c72eb5365fb09e3cccc0033cbb Mon Sep 17 00:00:00 2001 From: btee Date: Fri, 15 Mar 2024 17:45:19 +0100 Subject: [PATCH 1/4] Resolve application path with shutil.which Addresses non-intuitive behavior of `dotenv run python ...` on Windows --- src/dotenv/cli.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index 65ead461..7c09a5ff 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -1,6 +1,7 @@ import json import os import shlex +import shutil import sys from contextlib import contextmanager from subprocess import Popen @@ -189,6 +190,11 @@ def run_command(command: List[str], env: Dict[str, str]) -> int: cmd_env = os.environ.copy() cmd_env.update(env) + # Resolve path in a consistent way + app = shutil.which(command[0]) + if app is not None: + command = (app,) + command[1:] + p = Popen(command, universal_newlines=True, bufsize=0, From 0b5af3df1a430be088dd8ef849f77e4744818556 Mon Sep 17 00:00:00 2001 From: bkramarski Date: Fri, 15 Mar 2024 18:48:26 +0100 Subject: [PATCH 2/4] Align annotations to Click behavior --- src/dotenv/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index 7c09a5ff..56031f42 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -5,7 +5,7 @@ import sys from contextlib import contextmanager from subprocess import Popen -from typing import Any, Dict, IO, Iterator, List +from typing import Any, Dict, IO, Iterator, Tuple try: import click @@ -145,7 +145,7 @@ def unset(ctx: click.Context, key: Any) -> None: help="Override variables from the environment file with those from the .env file.", ) @click.argument('commandline', nargs=-1, type=click.UNPROCESSED) -def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: +def run(ctx: click.Context, override: bool, commandline: Tuple[str, ...]) -> None: """Run command with environment variables present.""" file = ctx.obj['FILE'] if not os.path.isfile(file): @@ -166,7 +166,7 @@ def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: exit(ret) -def run_command(command: List[str], env: Dict[str, str]) -> int: +def run_command(command: Tuple[str, ...], env: Dict[str, str]) -> int: """Run command in sub process. Runs the command in a sub process with the variables from `env` From d559c3123de0539ba1ff4e0d25125498bd9e5f65 Mon Sep 17 00:00:00 2001 From: bkramarski Date: Fri, 15 Mar 2024 18:49:11 +0100 Subject: [PATCH 3/4] Delay default file path evaluation in CLI --- 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 56031f42..2d69ae6e 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -33,7 +33,7 @@ def enumerate_env(): @click.group() -@click.option('-f', '--file', default=enumerate_env(), +@click.option('-f', '--file', default=enumerate_env, type=click.Path(file_okay=True), help="Location of the .env file, defaults to .env file in current working directory.") @click.option('-q', '--quote', default='always', From e0a5ac167c001c00164181ba424c8f402bacdd4c Mon Sep 17 00:00:00 2001 From: bkramarski Date: Fri, 15 Mar 2024 18:50:44 +0100 Subject: [PATCH 4/4] Correct and extend CLI tests --- tests/test_cli.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index fc309b48..b43ce2a1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -208,18 +208,27 @@ def test_run_with_other_env(dotenv_path): assert result == "b\n" -def test_run_without_cmd(cli): +def test_run_without_env(cli): result = cli.invoke(dotenv_cli, ['run']) assert result.exit_code == 2 assert "Invalid value for '-f'" in result.output +def test_run_without_cmd(cli): + Path(".env").write_text("") + result = cli.invoke(dotenv_cli, ['run']) + + assert result.exit_code == 1 + assert "No command given" in result.output + + def test_run_with_invalid_cmd(cli): + Path(".env").write_text("") result = cli.invoke(dotenv_cli, ['run', 'i_do_not_exist']) - assert result.exit_code == 2 - assert "Invalid value for '-f'" in result.output + assert result.exit_code == 1 + assert isinstance(result.exception, FileNotFoundError) def test_run_with_version(cli):