未验证 提交 950885f0 编写于 作者: P Phil Jones 提交者: GitHub

feat: Add an override option to the env_file script option (#1299)

This allows the user to specify that the env_file should override any
existing environment variables. This is not the default as the
environment the code runs it should take precedence.
上级 d5c88a1b
......@@ -146,6 +146,15 @@ start.cmd = "flask run -p 54321"
start.env_file = ".env"
```
The variables within the dotenv file will *not* override any existing environment variables.
If you want the dotenv file to override existing environment variables use the following:
```toml
[tool.pdm.scripts]
start.cmd = "flask run -p 54321"
start.env_file.override = ".env"
```
!!! note
A dotenv file specified on a composite task level will override those defined by called tasks.
......
Add a env_file.override option that allows the user to specify that
the env_file should override any existing environment variables. This
is not the default as the environment the code runs it should take
precedence.
......@@ -21,9 +21,13 @@ from pdm.project import Project
from pdm.utils import is_path_relative_to
class EnvFileOptions(TypedDict, total=True):
override: str
class TaskOptions(TypedDict, total=False):
env: Mapping[str, str]
env_file: str | None
env_file: EnvFileOptions | str | None
help: str
site_packages: bool
......@@ -119,12 +123,19 @@ class TaskRunner:
shell: bool = False,
site_packages: bool = False,
env: Mapping[str, str] | None = None,
env_file: str | None = None,
env_file: EnvFileOptions | str | None = None,
) -> int:
"""Run command in a subprocess and return the exit code."""
project = self.project
process_env = {}
if env_file:
process_env = os.environ.copy()
if env_file is not None:
if isinstance(env_file, str):
path = env_file
override = False
else:
path = env_file["override"]
override = True
import dotenv
project.core.ui.echo(
......@@ -132,10 +143,11 @@ class TaskRunner:
err=True,
verbosity=termui.Verbosity.DETAIL,
)
process_env = dotenv.dotenv_values(
project.root / env_file, encoding="utf-8"
)
process_env.update(os.environ)
dotenv_env = dotenv.dotenv_values(project.root / path, encoding="utf-8")
if override:
process_env = {**process_env, **dotenv_env}
else:
process_env = {**dotenv_env, **process_env}
pythonpath = process_env.get("PYTHONPATH", "").split(os.pathsep)
pythonpath = [PEP582_PATH] + [
p for p in pythonpath if "pdm/pep582" not in p.replace("\\", "/")
......
......@@ -230,20 +230,26 @@ def test_run_script_with_env_defined(project, invoke, capfd):
assert capfd.readouterr()[0].strip() == "bar"
def test_run_script_with_dotenv_file(project, invoke, capfd):
def test_run_script_with_dotenv_file(project, invoke, capfd, monkeypatch):
(project.root / "test_script.py").write_text(
"import os; print(os.getenv('FOO'), os.getenv('BAR'))"
)
project.tool_settings["scripts"] = {
"_": {"env": {"BAR": "foo"}},
"test_script": {"cmd": "python test_script.py", "env_file": ".env"},
"test_override": {
"cmd": "python test_script.py",
"env_file": {"override": ".env"},
},
"test_default": {"cmd": "python test_script.py", "env_file": ".env"},
}
project.write_pyproject()
monkeypatch.setenv("BAR", "foo")
(project.root / ".env").write_text("FOO=bar\nBAR=override")
capfd.readouterr()
with cd(project.root):
invoke(["run", "test_script"], obj=project)
invoke(["run", "test_default"], obj=project)
assert capfd.readouterr()[0].strip() == "bar foo"
invoke(["run", "test_override"], obj=project)
assert capfd.readouterr()[0].strip() == "bar override"
def test_run_script_override_global_env(project, invoke, capfd):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册