_dotenv.py 2.0 KB

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