c7998de8bb
- config_from_env_py_infra: dataclass + field metadata, tipos str/int/float/bool/list - dotenv_load_py_infra: parser .env con semantica de no-sobreescritura - 15 tests unitarios Python, todos PASS - registry.db actualizado con fn index (685 funciones, 109 tipos) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
"""dotenv_load — parsea un archivo .env y popula os.environ sin sobreescribir."""
|
|
|
|
import os
|
|
|
|
|
|
def dotenv_load(path: str) -> None:
|
|
"""Parsea un archivo .env y setea variables en os.environ.
|
|
|
|
Reglas de parseo:
|
|
- Lineas que empiezan con # (tras strip) son comentarios y se ignoran.
|
|
- Lineas vacias se ignoran.
|
|
- Formato esperado: KEY=VALUE (separador es el primer =).
|
|
- Valores con comillas simples o dobles externas se stripean.
|
|
- Variables ya presentes en os.environ NO se sobreescriben.
|
|
|
|
Args:
|
|
path: ruta al archivo .env.
|
|
|
|
Returns:
|
|
None
|
|
|
|
Raises:
|
|
FileNotFoundError: si el archivo no existe.
|
|
ValueError: si una linea no tiene el separador '='.
|
|
"""
|
|
with open(path, encoding="utf-8") as fh:
|
|
for lineno, raw_line in enumerate(fh, start=1):
|
|
line = raw_line.strip()
|
|
|
|
# skip blanks and comments
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
|
|
if "=" not in line:
|
|
raise ValueError(
|
|
f"dotenv_load: {path!r} line {lineno}: missing '=' in {line!r}"
|
|
)
|
|
|
|
key, _, val = line.partition("=")
|
|
key = key.strip()
|
|
val = _strip_quotes(val)
|
|
|
|
# only set if not already present
|
|
if key not in os.environ or os.environ[key] == "":
|
|
os.environ[key] = val
|
|
|
|
|
|
def _strip_quotes(s: str) -> str:
|
|
"""Remove surrounding single or double quotes."""
|
|
if len(s) >= 2:
|
|
if (s[0] == '"' and s[-1] == '"') or (s[0] == "'" and s[-1] == "'"):
|
|
return s[1:-1]
|
|
return s
|