Skip to content

Commit 1ee3030

Browse files
authored
feat: Update env command to prefer current environment values in .env… (#193)
1 parent d1b6570 commit 1ee3030

File tree

5 files changed

+51
-8
lines changed

5 files changed

+51
-8
lines changed

docs/developer-guide/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Use the `wurzel env` helper to inspect or validate the variables your pipeline n
8080
# Show required env vars (toggle optional ones via --only-required)
8181
wurzel env examples.pipeline.pipelinedemo:pipeline --only-required
8282

83-
# Generate a .env snippet with defaults
83+
# Generate a .env snippet (prefers values already present in your shell)
8484
wurzel env examples.pipeline.pipelinedemo:pipeline --gen-env > .env.sample
8585

8686
# Fail fast when something is missing

tests/cli/cmd_env_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ def test_format_env_snippet_matches_expected_layout():
4545
)
4646

4747

48+
def test_format_env_snippet_prefers_current_env_values():
49+
reqs = cmd_env.collect_env_requirements(pipelinedemo.pipeline)
50+
51+
snippet = cmd_env.format_env_snippet(
52+
reqs,
53+
current_env={
54+
"MANUALMARKDOWNSTEP__FOLDER_PATH": "/tmp/data",
55+
"SIMPLESPLITTERSTEP__BATCH_SIZE": "256",
56+
},
57+
)
58+
59+
assert "MANUALMARKDOWNSTEP__FOLDER_PATH=/tmp/data" in snippet
60+
assert "SIMPLESPLITTERSTEP__BATCH_SIZE=256" in snippet
61+
62+
4863
def test_validate_env_vars_reports_missing(env):
4964
env.clear()
5065
issues = cmd_env.validate_env_vars(pipelinedemo.pipeline, allow_extra_fields=False)

tests/cli/main_test.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,30 @@ def test_env_only_required_filters_optional(capsys, monkeypatch):
199199
assert "SIMPLESPLITTERSTEP__BATCH_SIZE" not in captured.out
200200

201201

202-
def test_env_gen_env_outputs_env_file(capsys, monkeypatch):
202+
def test_env_gen_env_outputs_env_file(capsys, monkeypatch, env):
203+
monkeypatch.setattr(main, "console", main.console.__class__(force_terminal=False, width=200))
204+
env.set("MANUALMARKDOWNSTEP__FOLDER_PATH", "/tmp/custom")
205+
env.set("SIMPLESPLITTERSTEP__BATCH_SIZE", "256")
206+
207+
main.env_cmd("examples.pipeline.pipelinedemo:pipeline", gen_env=True)
208+
captured = capsys.readouterr()
209+
expected = (
210+
"# Generated env vars\n\n"
211+
"# ManualMarkdownStep\n"
212+
"MANUALMARKDOWNSTEP__FOLDER_PATH=/tmp/custom\n\n" # pragma: allowlist secret
213+
"# SimpleSplitterStep\n"
214+
"SIMPLESPLITTERSTEP__BATCH_SIZE=256\n"
215+
"SIMPLESPLITTERSTEP__NUM_THREADS=4\n"
216+
"SIMPLESPLITTERSTEP__TOKEN_COUNT_MIN=64\n"
217+
"SIMPLESPLITTERSTEP__TOKEN_COUNT_MAX=1024\n"
218+
"SIMPLESPLITTERSTEP__TOKEN_COUNT_BUFFER=32\n"
219+
"SIMPLESPLITTERSTEP__TOKENIZER_MODEL=gpt-3.5-turbo\n"
220+
"SIMPLESPLITTERSTEP__SENTENCE_SPLITTER_MODEL=de_core_news_sm\n\n\n"
221+
)
222+
assert captured.out == expected
223+
224+
225+
def test_env_gen_env_outputs_env_file_empty(capsys, monkeypatch):
203226
monkeypatch.setattr(main, "console", main.console.__class__(force_terminal=False, width=200))
204227
main.env_cmd("examples.pipeline.pipelinedemo:pipeline", gen_env=True)
205228
captured = capsys.readouterr()

wurzel/cli/_main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ def env_cmd(
500500
return
501501

502502
if gen_env:
503-
typer.echo(format_env_snippet(to_display))
503+
typer.echo(format_env_snippet(to_display, current_env=os.environ))
504504
return
505505

506506
_print_requirements(to_display)

wurzel/cli/cmd_env.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
from collections.abc import Mapping
89
from json import dumps
910
from types import NoneType
1011
from typing import TYPE_CHECKING
@@ -74,19 +75,23 @@ def collect_env_requirements(pipeline: TypedStep) -> list[EnvVarRequirement]:
7475
return sorted(requirements, key=lambda req: (req.step_index, req.field_index))
7576

7677

77-
def format_env_snippet(requirements: list[EnvVarRequirement]) -> str:
78+
def format_env_snippet(
79+
requirements: list[EnvVarRequirement],
80+
current_env: Mapping[str, str] | None = None,
81+
) -> str:
7882
"""Return .env-style representation of requirements grouped by step."""
7983
lines: list[str] = ["# Generated env vars"]
8084
current_step = None
85+
env_values = current_env or {}
8186
for req in requirements:
8287
if req.step_name != current_step:
8388
lines.append("")
8489
lines.append(f"# {req.step_name}")
8590
current_step = req.step_name
86-
default = req.default
87-
if not default:
88-
default = ""
89-
lines.append(f"{req.env_var}={default}")
91+
value = req.default or ""
92+
if current_env is not None and req.env_var in env_values:
93+
value = env_values[req.env_var]
94+
lines.append(f"{req.env_var}={value}")
9095
lines.append("")
9196
return "\n".join(lines) + "\n"
9297

0 commit comments

Comments
 (0)