From 700b5be6f828a49cd8232e1ce7ef71cdd98babbd Mon Sep 17 00:00:00 2001 From: mwiegand Date: Wed, 6 May 2026 19:57:56 +0200 Subject: [PATCH] feat(host): add _emit_step helper for lifecycle logging --- l4d2host/instances.py | 8 ++++++++ l4d2host/tests/test_initialize.py | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/l4d2host/instances.py b/l4d2host/instances.py index 256cd7c..4b2285e 100644 --- a/l4d2host/instances.py +++ b/l4d2host/instances.py @@ -8,6 +8,14 @@ from l4d2host.service_control import start_service, stop_service from l4d2host.spec import load_spec +def _emit_step(msg: str, on_stdout: Callable[[str], None] | None, passthrough: bool) -> None: + formatted = f"Step: {msg}" + if on_stdout is not None: + on_stdout(formatted) + elif passthrough: + print(formatted, flush=True) + + DEFAULT_ROOT = DEFAULT_LEFT4ME_ROOT diff --git a/l4d2host/tests/test_initialize.py b/l4d2host/tests/test_initialize.py index 5868771..3252b98 100644 --- a/l4d2host/tests/test_initialize.py +++ b/l4d2host/tests/test_initialize.py @@ -1,6 +1,8 @@ +import sys +from io import StringIO from pathlib import Path -from l4d2host.instances import initialize_instance +from l4d2host.instances import initialize_instance, _emit_step def test_initialize_writes_files(tmp_path: Path) -> None: @@ -31,3 +33,21 @@ def test_initialize_uses_configured_left4me_root(tmp_path: Path, monkeypatch) -> env = (tmp_path / "instances/alpha/instance.env").read_text() assert f"L4D2_LOWERDIRS={tmp_path}/overlays/standard:{tmp_path}/installation" in env + + +def test_emit_step_uses_callback() -> None: + calls: list[str] = [] + _emit_step("test step", on_stdout=calls.append, passthrough=False) + assert calls == ["Step: test step"] + + +def test_emit_step_uses_passthrough_stdout(monkeypatch) -> None: + fake_out = StringIO() + monkeypatch.setattr(sys, "stdout", fake_out) + _emit_step("passthrough step", on_stdout=None, passthrough=True) + assert fake_out.getvalue() == "Step: passthrough step\n" + + +def test_emit_step_does_nothing_if_no_target() -> None: + _emit_step("silent step", on_stdout=None, passthrough=False) +