[配置]:完成 .env 文件读取配置,包含自动加载、CLI 参数、测试覆盖和中文说明
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
@@ -25,9 +24,11 @@ class AppConfig:
|
||||
context_max_chars: int = 12000
|
||||
|
||||
@classmethod
|
||||
def from_env(cls, prefix: str = "OWNER_") -> "AppConfig":
|
||||
def from_dotenv(cls, path: str | Path = ".env", prefix: str = "OWNER_") -> "AppConfig":
|
||||
values = parse_dotenv(Path(path))
|
||||
|
||||
def get(name: str, default: str | None = None) -> str | None:
|
||||
value = os.environ.get(f"{prefix}{name}")
|
||||
value = values.get(f"{prefix}{name}")
|
||||
return default if value is None or value == "" else value
|
||||
|
||||
return cls(
|
||||
@@ -47,6 +48,10 @@ class AppConfig:
|
||||
context_max_chars=int(get("CONTEXT_MAX_CHARS", "12000") or "12000"),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_env(cls, prefix: str = "OWNER_") -> "AppConfig":
|
||||
return cls.from_dotenv(".env", prefix=prefix)
|
||||
|
||||
def require_llm_credentials(self) -> None:
|
||||
if not self.llm_api_key:
|
||||
raise ProviderError(
|
||||
@@ -100,3 +105,32 @@ class AppConfig:
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def parse_dotenv(path: Path) -> dict[str, str]:
|
||||
if not path.exists():
|
||||
return {}
|
||||
values: dict[str, str] = {}
|
||||
for line_no, raw_line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
if line.startswith("export "):
|
||||
line = line.removeprefix("export ").strip()
|
||||
if "=" not in line:
|
||||
raise ValueError(f"invalid .env line {line_no}: missing '='")
|
||||
key, value = line.split("=", 1)
|
||||
key = key.strip()
|
||||
value = _strip_dotenv_value(value.strip())
|
||||
if not key:
|
||||
raise ValueError(f"invalid .env line {line_no}: empty key")
|
||||
values[key] = value
|
||||
return values
|
||||
|
||||
|
||||
def _strip_dotenv_value(value: str) -> str:
|
||||
if len(value) >= 2 and value[0] == value[-1] and value[0] in {"'", '"'}:
|
||||
return value[1:-1]
|
||||
if " #" in value:
|
||||
return value.split(" #", 1)[0].rstrip()
|
||||
return value
|
||||
|
||||
Reference in New Issue
Block a user