44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
|
|
_ENV_NAME = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
|
|
|
|
def load_env_file(path: Path) -> bool:
|
|
"""Load a simple dotenv file without overriding the process environment."""
|
|
path = Path(path)
|
|
if not path.is_file():
|
|
return False
|
|
for raw_line in path.read_text(encoding="utf-8-sig").splitlines():
|
|
line = raw_line.strip()
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
if line.startswith("export "):
|
|
line = line[7:].lstrip()
|
|
key, separator, value = line.partition("=")
|
|
key = key.strip()
|
|
if not separator or not _ENV_NAME.fullmatch(key):
|
|
continue
|
|
value = value.strip()
|
|
if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}:
|
|
value = value[1:-1]
|
|
os.environ.setdefault(key, value)
|
|
return True
|
|
|
|
|
|
def load_project_environment(base_dir: Path) -> Path | None:
|
|
"""Select local/production dotenv while preserving injected server secrets."""
|
|
base_dir = Path(base_dir)
|
|
explicit = os.environ.get("DJANGO_ENV_FILE", "").strip()
|
|
if explicit:
|
|
selected = Path(explicit)
|
|
if not selected.is_absolute():
|
|
selected = base_dir / selected
|
|
else:
|
|
settings_module = os.environ.get("DJANGO_SETTINGS_MODULE", "")
|
|
selected = base_dir / (".env.local" if settings_module.endswith(".dev") else ".env")
|
|
load_env_file(selected)
|
|
return selected if selected.is_file() else None
|