From c5db1d7ba249ee84fd620d2737974899b3624b6b Mon Sep 17 00:00:00 2001 From: anti Date: Mon, 27 Apr 2026 22:55:58 -0400 Subject: [PATCH] fix(config-ini): strip inline # and ; comments from values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The module docstring teaches inline comments — `mode = master # or "agent"` is the canonical example for the [decnet] section. Python's configparser ignores those by default unless inline_comment_prefixes is set explicitly, so the comment became part of the value and downstream validators rejected it ("mode must be 'agent' or 'master', got 'master # or \"agent\"'"). Hit live on first VPS deploy: every CLI invocation crashed at import time with a stack trace that didn't make it obvious the docstring's example was the trigger. Now the parser does what the docs promise. --- decnet/config_ini.py | 9 ++++++++- tests/config/test_config_ini.py | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) 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,