diff --git a/decnet/config_ini.py b/decnet/config_ini.py index 4732f3f4..a3747003 100644 --- a/decnet/config_ini.py +++ b/decnet/config_ini.py @@ -158,7 +158,14 @@ def load_ini_config(path: Optional[Path] = None) -> Optional[Path]: if not path.is_file(): return None - parser = configparser.ConfigParser() + # The docstring at the top of this module advertises inline ``#`` and + # ``;`` comments (e.g. ``mode = master # or "agent"``). Python's + # ``configparser`` only recognises those when ``inline_comment_prefixes`` + # is set explicitly — without it, the comment becomes part of the value + # and downstream validators reject it ("mode must be 'agent' or 'master', + # got 'master # or \"agent\"'"). Match what the docs + # promise. + parser = configparser.ConfigParser(inline_comment_prefixes=("#", ";")) parser.read(path) # [decnet] first — mode/disallow-master/log-directory. These seed the diff --git a/tests/config/test_config_ini.py b/tests/config/test_config_ini.py index 1e0fce5a..5355a62a 100644 --- a/tests/config/test_config_ini.py +++ b/tests/config/test_config_ini.py @@ -27,6 +27,24 @@ def test_missing_file_is_noop(monkeypatch, tmp_path): assert "DECNET_AGENT_PORT" not in os.environ +def test_inline_comments_stripped_from_values(monkeypatch, tmp_path): + """The module docstring teaches inline ``#`` comments — the parser + must accept them. Hit live on the first VPS deploy 2026-04-28: a + ``mode = master # or "agent"`` line caused the value to be parsed + as ``master # or "agent"`` and downstream + validators rejected it.""" + _scrub(monkeypatch, "DECNET_MODE", "DECNET_API_PORT") + ini = _write_ini(tmp_path, """ +[decnet] +mode = master # inline hash comment +[master] +api-port = 8000 ; inline semi comment +""") + load_ini_config(ini) + assert os.environ["DECNET_MODE"] == "master" + assert os.environ["DECNET_API_PORT"] == "8000" + + def test_agent_section_only_loaded_when_mode_agent(monkeypatch, tmp_path): _scrub( monkeypatch,