Skip to content

Commit a3e6e2f

Browse files
authored
Merge branch 'main' into add-windows-ci
2 parents c91abd8 + 9f3b8b5 commit a3e6e2f

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

src/dotenv/cli.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,21 @@ def unset(ctx: click.Context, key: Any) -> None:
156156
sys.exit(1)
157157

158158

159-
@cli.command(context_settings={"ignore_unknown_options": True})
159+
@cli.command(
160+
context_settings={
161+
"allow_extra_args": True,
162+
"allow_interspersed_args": False,
163+
"ignore_unknown_options": True,
164+
}
165+
)
160166
@click.pass_context
161167
@click.option(
162168
"--override/--no-override",
163169
default=True,
164170
help="Override variables from the environment file with those from the .env file.",
165171
)
166172
@click.argument("commandline", nargs=-1, type=click.UNPROCESSED)
167-
def run(ctx: click.Context, override: bool, commandline: List[str]) -> None:
173+
def run(ctx: click.Context, override: bool, commandline: tuple[str, ...]) -> None:
168174
"""Run command with environment variables present."""
169175
file = ctx.obj["FILE"]
170176
if not os.path.isfile(file):
@@ -180,7 +186,8 @@ def run(ctx: click.Context, override: bool, commandline: List[str]) -> None:
180186
if not commandline:
181187
click.echo("No command given.")
182188
sys.exit(1)
183-
run_command(commandline, dotenv_as_dict)
189+
190+
run_command([*commandline, *ctx.args], dotenv_as_dict)
184191

185192

186193
def run_command(command: List[str], env: Dict[str, str]) -> None:

tests/test_cli.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import os
2+
import subprocess
23
import sys
34
from pathlib import Path
4-
from typing import Optional
5+
from typing import Optional, Sequence
56

67
import pytest
78

@@ -13,6 +14,21 @@
1314
import sh
1415

1516

17+
def invoke_sub(args: Sequence[str]) -> subprocess.CompletedProcess:
18+
"""
19+
Invoke the `dotenv` CLI in a subprocess.
20+
21+
This is necessary to test subcommands like `dotenv run` that replace the
22+
current process.
23+
"""
24+
25+
return subprocess.run(
26+
["dotenv", *args],
27+
capture_output=True,
28+
text=True,
29+
)
30+
31+
1632
@pytest.mark.parametrize(
1733
"output_format,content,expected",
1834
(
@@ -258,3 +274,29 @@ def test_run_with_version(cli):
258274

259275
assert result.exit_code == 0
260276
assert result.output.strip().endswith(__version__)
277+
278+
279+
def test_run_with_command_flags(dotenv_path):
280+
"""
281+
Check that command flags passed after `dotenv run` are not interpreted.
282+
283+
Here, we want to run `printenv --version`, not `dotenv --version`.
284+
"""
285+
286+
result = invoke_sub(["--file", dotenv_path, "run", "printenv", "--version"])
287+
288+
assert result.returncode == 0
289+
assert result.stdout.strip().startswith("printenv ")
290+
291+
292+
def test_run_with_dotenv_and_command_flags(cli, dotenv_path):
293+
"""
294+
Check that dotenv flags supersede command flags.
295+
"""
296+
297+
result = invoke_sub(
298+
["--version", "--file", dotenv_path, "run", "printenv", "--version"]
299+
)
300+
301+
assert result.returncode == 0
302+
assert result.stdout.strip().startswith("dotenv, version")

0 commit comments

Comments
 (0)