fix(followups): F2 - Python entry points report an unreadable env file in one line

A .mam.env that exists but cannot be read or decoded stopped the Python
entry points with an EnvFileError traceback, while the wrapper printed one
`ERROR:` line and exited 1 (PR #43 review claude S1). The mains that load the
env file - publish_event, registry, job_subscriber, cli, bench, heartbeat and
remote - now call mqtt_common.load_env_or_report(), which prints
`ERROR: <path>: cannot read (<exception type>)` and lets the main return 1.
No value or file content is printed. ensure_env_loaded() still raises: no
library function exits the process.

Test: every entry point, for a 000 file and an undecodable one, ends with
exactly that line and rc 1 and creates nothing (14 cases; all 14 fail at
0051fd6 with a traceback).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-02 08:09:46 +09:00
1 parent 75936f11c6
commit 5edf913d22
9 files changed
+73 -9

No files matched your search

+41
View File
@@ -180,6 +180,47 @@ def test_a1_a_file_that_cannot_be_read_stops_both_loaders(tmp_path, kind):
f.chmod(0o600)
# Follow-up F2 (PR #43 claude S1): every main that loads the env file, with
# arguments its parser accepts when it parses before loading.
ENTRY_POINTS = {
"publish_event": ["--job", "abcd1234", "--event", "progress", "--registry-dir", "reg"],
"registry": [],
"job_subscriber": ["--job", "abcd1234", "--registry-dir", "reg"],
"cli": [],
"bench": [],
"heartbeat": ["--job", "abcd1234", "--interval", "30", "--registry-dir", "reg"],
"remote": ["run", "--session", "s", "--registry-dir", "reg"],
}
@pytest.mark.parametrize("kind", ["permission", "utf8"])
@pytest.mark.parametrize("module", sorted(ENTRY_POINTS))
def test_a1_python_entry_points_report_an_unreadable_file_in_one_line(tmp_path, module, kind):
"""The wrapper's shape at every Python entry point: one `ERROR:` line
naming the path and the exception type, rc 1, no traceback, no value."""
f = tmp_path / "broken.env"
if kind == "permission":
if os.geteuid() == 0:
pytest.skip("root reads a 000 file")
f.write_text("PROBE_A=one\n")
f.chmod(0)
cause = "PermissionError"
else:
f.write_bytes(b"PROBE_A=one\nPROBE_B=\xff\xfe\n")
cause = "UnicodeDecodeError"
try:
# main() itself: `-m` adds runpy's warning (the package __init__ imports these modules)
code = f"import sys; from lib_py.delegation import {module} as m; sys.exit(m.main(sys.argv[1:]))"
res = subprocess.run([sys.executable, "-c", code, *ENTRY_POINTS[module]],
capture_output=True, text=True, env=_env(tmp_path, f), cwd=str(tmp_path), timeout=60)
finally:
f.chmod(0o600)
assert res.returncode == 1, (res.returncode, res.stderr[-500:])
assert res.stderr.strip().splitlines() == [f"ERROR: {f}: cannot read ({cause})"], res.stderr[-500:]
assert "one" not in res.stdout + res.stderr
assert not (tmp_path / "reg").exists(), "nothing ran past the env file"
def test_a1_a_nul_line_is_skipped_by_both_loaders(tmp_path):
"""Review R4: no environment can carry a NUL byte. Both loaders skip that
line with a warning naming it (not its value) and keep the lines around it."""