From 5adc857d52984d47cae208224a862d32554af3e7 Mon Sep 17 00:00:00 2001 From: ROTl24 <119035617+ROTl24@users.noreply.github.com> Date: Tue, 8 Sep 2026 10:14:28 +0800 Subject: [PATCH] fix: honor CLI override mode during variable expansion --- src/dotenv/cli.py | 4 ++-- tests/test_cli.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index 79613e28..72c81816 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -17,7 +17,7 @@ ) sys.exit(1) -from .main import dotenv_values, set_key, unset_key +from .main import DotEnv, dotenv_values, set_key, unset_key from .version import __version__ @@ -190,7 +190,7 @@ def run(ctx: click.Context, override: bool, commandline: tuple[str, ...]) -> Non ) dotenv_as_dict = { k: v - for (k, v) in dotenv_values(file).items() + for (k, v) in DotEnv(file, override=override, encoding="utf-8").dict().items() if v is not None and (override or k not in os.environ) } diff --git a/tests/test_cli.py b/tests/test_cli.py index d4e3ad4d..a7afae34 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ import os +import sys from pathlib import Path from typing import Optional @@ -211,6 +212,39 @@ def test_run_with_existing_variable_not_overridden(tmp_path): check_process(result, exit_code=0, stdout="C\n") +@pytest.mark.parametrize("options", [[], ["--override"], ["--no-override"]]) +@pytest.mark.parametrize("existing_value", [None, "environment", ""]) +def test_run_interpolation_respects_override(tmp_path, options, existing_value): + (tmp_path / ".env").write_text( + "DOTENV_TEST_BASE=file\nDOTENV_TEST_DERIVED=${DOTENV_TEST_BASE}/suffix\n" + ) + env = dict(os.environ) + env.pop("DOTENV_TEST_BASE", None) + env.pop("DOTENV_TEST_DERIVED", None) + if existing_value is not None: + env["DOTENV_TEST_BASE"] = existing_value + + result = run_dotenv( + [ + "run", + *options, + sys.executable, + "-c", + "import os; print(os.environ['DOTENV_TEST_BASE']); " + "print(os.environ['DOTENV_TEST_DERIVED'])", + ], + cwd=tmp_path, + env=env, + ) + + expected = ( + existing_value + if options == ["--no-override"] and existing_value is not None + else "file" + ) + check_process(result, exit_code=0, stdout=f"{expected}\n{expected}/suffix\n") + + def test_run_with_none_value(tmp_path): (tmp_path / ".env").write_text("A=x\nc")