j139 dotenv: strip trailing inline comments and warn on non-token values
A `#` preceded by whitespace and outside quotes now ends the value, so `TR_DEBUG_DRAW=0 # hides the grid` resolves to `0` instead of the whole tail. Values that are still not plain tokens (whitespace, `#`, an unclosed quote) get one `[dotenv] WARNING` line naming file, key, raw value and the fact that the reader falls back to its DEFAULT, instead of being applied silently. Guard test 29 -> 47 checks.
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
## * resolution precedence (flag > TR_ENV_FILE > ./.env > .env next to the
|
||||
## executable > none);
|
||||
## * the FILE WINS over the real environment, and the conflict is reported;
|
||||
## * a junky value (unrecognised) is WARNED ABOUT at load time instead of
|
||||
## silently becoming the reader's default (j139);
|
||||
## * an explicitly requested missing file raises (the caller then exits
|
||||
## nonzero), while a missing DEFAULT file is a silent no-op.
|
||||
|
||||
@@ -166,12 +168,76 @@ proc testMissingFiles() =
|
||||
check "no file at all is a silent no-op",
|
||||
loadEnvFile(EnvFileChoice(path: "", source: "none", explicit: false)).len == 0
|
||||
|
||||
# ── 5. inline comments (j139) and the junk-value warning ─────────────────────
|
||||
|
||||
proc testInlineComments() =
|
||||
let e = parseEnvFileContent(
|
||||
"A=value # comment\n" &
|
||||
"B=\"a # b\"\n" &
|
||||
"C='a # b'\n" &
|
||||
"D=value#notacomment\n" &
|
||||
"E=# comment\n" &
|
||||
"# whole line\n" &
|
||||
"F=0 # hides the heat grid\n" &
|
||||
"G=both\n", "inline.env")
|
||||
check "inline comment file yields 7 entries", e.len == 7
|
||||
if e.len == 7:
|
||||
check "`KEY=value # comment` -> value", e[0].key == "A" and e[0].value == "value"
|
||||
check "a `#` inside double quotes is DATA", e[1].value == "a # b"
|
||||
check "a `#` inside single quotes is DATA", e[2].value == "a # b"
|
||||
check "`KEY=value#notacomment` keeps the `#` (no whitespace before it)",
|
||||
e[3].value == "value#notacomment"
|
||||
check "`KEY=# comment` -> empty value (not an error)", e[4].value == ""
|
||||
check "the reported bug shape `0 # comment` -> `0`", e[5].value == "0"
|
||||
check "a line whose only content is a comment is still skipped", e[6].value == "both"
|
||||
|
||||
check "stripInlineComment is pure and exact",
|
||||
stripInlineComment("x # y").strip == "x" and
|
||||
stripInlineComment(" # y").strip == "" and
|
||||
stripInlineComment("\"a # b\"").strip == "\"a # b\""
|
||||
|
||||
proc testJunkWarning() =
|
||||
check "a plain token is never junky",
|
||||
not looksJunky("0") and not looksJunky("off") and
|
||||
not looksJunky("1.0,1.25") and
|
||||
not looksJunky("/tmp/modularbot.log") and not looksJunky("")
|
||||
check "whitespace / `#` / unbalanced quotes are junky",
|
||||
looksJunky("0 # hides the grid") and looksJunky("a # b") and
|
||||
looksJunky("\"unclosed")
|
||||
|
||||
# A junky value the inline-comment rule CANNOT fix: an unclosed quote, so
|
||||
# the `#` is (correctly) treated as data and the whole tail stays in the value.
|
||||
let f = writeTmp("junk.env", "TR_TEST_JUNK_J139=\"0 # hides the grid\n")
|
||||
let conflicts = applyEnvFile(f)
|
||||
check "a junky value is still APPLIED verbatim (the reader decides)",
|
||||
conflicts.len == 0 and
|
||||
getEnv("TR_TEST_JUNK_J139") == "\"0 # hides the grid"
|
||||
delEnv("TR_TEST_JUNK_J139")
|
||||
|
||||
# the warning path itself: one line per offending key, naming file, key,
|
||||
# raw value and what is used.
|
||||
let w = junkWarnings(parseEnvFileContent(readFile(f), f), f)
|
||||
check "a junky value produces exactly one warning",
|
||||
w.len == 1
|
||||
check "the warning names the file", w.len == 1 and f in w[0]
|
||||
check "the warning names the key and the raw value",
|
||||
w.len == 1 and "TR_TEST_JUNK_J139" in w[0] and "# hides the grid" in w[0]
|
||||
check "the warning says what is used and how to fix it",
|
||||
w.len == 1 and "DEFAULT" in w[0] and "its own line" in w[0]
|
||||
check "a clean file produces no warning",
|
||||
junkWarnings(parseEnvFileContent("A=0 # fine\nB=1.0,1.25\n", "c.env"),
|
||||
"c.env").len == 0
|
||||
check "one line per key, no spam",
|
||||
junkWarnings(parseEnvFileContent("A=x y\nB=p q\n", "d.env"), "d.env").len == 2
|
||||
|
||||
# ── driver ───────────────────────────────────────────────────────────────────
|
||||
|
||||
testParser()
|
||||
testResolution()
|
||||
testFileWins()
|
||||
testMissingFiles()
|
||||
testInlineComments()
|
||||
testJunkWarning()
|
||||
|
||||
echo "\n", checks, " checks, ", failures, " failure(s)"
|
||||
if failures > 0:
|
||||
|
||||
Reference in New Issue
Block a user