_dotenv.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. # AI-generated module (ChatGPT)
  2. import re
  3. def load_dotenv(dotenv_str: str, environ: dict[str, str] | None = None) -> dict[str, str]:
  4. """
  5. Parse a DOTENV-format string and return a dictionary of key-value pairs.
  6. Handles quoted values, comments, export keyword, and blank lines.
  7. """
  8. env: dict[str, str] = {}
  9. line_pattern = re.compile(
  10. r"""
  11. ^\s*
  12. (?:export[^\S\n]+)? # optional export
  13. ([A-Za-z_][A-Za-z0-9_]*) # key
  14. [^\S\n]*(=)?[^\S\n]*
  15. ( # value group
  16. (?:
  17. '(?:\\'|[^'])*' # single-quoted value
  18. | \"(?:\\\"|[^\"])*\" # double-quoted value
  19. | [^#\n\r]+? # unquoted value
  20. )
  21. )?
  22. [^\S\n]*(?:\#.*)?$ # optional inline comment
  23. """,
  24. re.VERBOSE,
  25. )
  26. for line in dotenv_str.splitlines():
  27. line = line.strip()
  28. if not line or line.startswith("#"):
  29. continue # Skip comments and empty lines
  30. match = line_pattern.match(line)
  31. if match:
  32. key = match.group(1)
  33. val = None
  34. if match.group(2): # if there is '='
  35. raw_val = match.group(3) or ""
  36. val = raw_val.strip()
  37. # Remove surrounding quotes if quoted
  38. if (val.startswith('"') and val.endswith('"')) or (val.startswith("'") and val.endswith("'")):
  39. val = val[1:-1]
  40. val = val.replace(r"\n", "\n").replace(r"\t", "\t").replace(r"\"", '"').replace(r"\\", "\\")
  41. if raw_val.startswith('"'):
  42. val = val.replace(r"\$", "$") # only in double quotes
  43. elif environ is not None:
  44. # Get it from the current environment
  45. val = environ.get(key)
  46. if val is not None:
  47. env[key] = val
  48. return env