"""Generate rust/collector/testdata/envfile_python_dotenv.json: python-dotenv's own parse + interpolation of tricky .env inputs, used by the Rust envfile tests so the collector reads .env exactly as the Python app does. uv run python rust/collector/testdata/gen_envfile_cases.py """ import io import json import os import random from pathlib import Path import dotenv from dotenv.main import DotEnv FIXED = [ "A=abc'def\nB=x\"y\nC=1\n", "A=1\nPOSTGRES_PASSWORD='abc\nB=2\n", "A=1\nPOSTGRES_PASSWORD= \nB=2\n", "POSTGRES_PASSWORD=\"ab'c\nB=2\n", " export A = spaced value # comment\nB=a#b\n# c\n\nC= \nD\n", "A='x\\'y'\nB=\"l1\\nl2\\t\\\"q\\\"\"\nC='multi\nline'\nD='a\\\\b'\n", "A='ab\\'", "A='x'y\nB=1\n", "HOME_FROM_ENV=file\nA=${HOME_FROM_ENV}/x\nB=${A}-${MISSING:-dflt}-${NOPE}\nC=$A ${A:x}\n", "A=1\r\nB=2\r\nA=3\r\n", "C= # c\nD=#x\nE= #x\n", "A#B=1\nexport\nexportA=2\n'q k'=3\n", "\ufeffA=bom\n", "A=\u00e9\u0e01\u0e02 # thai\n", ] KEYS = [ "A", "B", "C", "D", "E", "export A", "'A B'", "HOME_FROM_ENV", "#A", " A", "A B", ] SEPS = ["=", " = ", "= ", "", "\t=\t", "=="] VALUE_BITS = [ "abc", "'", '"', "\\", "#", " #c", "${A}", "${B:-d}", "${", "}", " ", "\t", "'q'", '"q"', "\\'", '\\"', "\\n", "x y", "${HOME_FROM_ENV}", "${:-z}", "$A", "\u0e01", ] EOLS = ["\n", "\r\n", "\r", ""] def random_case(rng: random.Random) -> str: lines = [] for _ in range(rng.randint(1, 5)): kind = rng.random() if kind < 0.1: lines.append(rng.choice(["", " ", "# comment", " # c ' \""])) else: value = "".join(rng.choice(VALUE_BITS) for _ in range(rng.randint(0, 4))) lines.append(rng.choice(KEYS) + rng.choice(SEPS) + value) lines.append(rng.choice(EOLS)) return "".join(lines) def expected(content: str): values = DotEnv( None, stream=io.StringIO(content), interpolate=True, override=False ).dict() return [[k, v] for k, v in values.items()] def main(): os.environ["HOME_FROM_ENV"] = "/home/x" for k in ("A", "B", "C", "D", "E", "MISSING", "NOPE"): os.environ.pop(k, None) rng = random.Random(20261018) inputs = FIXED + [random_case(rng) for _ in range(600)] cases = [{"input": c, "expected": expected(c)} for c in inputs] out = Path(__file__).with_name("envfile_python_dotenv.json") out.write_text( json.dumps( { "python_dotenv": dotenv.__dict__.get("__version__", "1.1.1"), "env": {"HOME_FROM_ENV": "/home/x"}, "cases": cases, }, ensure_ascii=True, indent=0, ), encoding="utf-8", ) print(f"{len(cases)} cases -> {out}") if __name__ == "__main__": import logging logging.disable(logging.WARNING) # python-dotenv warns on every bad line main()